Convert UserDefinedFunction to kotlin
This commit is contained in:
		
							parent
							
								
									e6e3965485
								
							
						
					
					
						commit
						ba6418a977
					
				@ -12,7 +12,7 @@ import java.io.PipedOutputStream
 | 
				
			|||||||
import java.io.PrintStream
 | 
					import java.io.PrintStream
 | 
				
			||||||
import java.text.MessageFormat.format
 | 
					import java.text.MessageFormat.format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LispMain @JvmOverloads constructor(var configuration: TerminalConfiguration = TerminalConfiguration()) {
 | 
					class LispMain constructor(var configuration: TerminalConfiguration = TerminalConfiguration()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    init {
 | 
					    init {
 | 
				
			||||||
        if (configuration.terminal == null) {
 | 
					        if (configuration.terminal == null) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,169 +0,0 @@
 | 
				
			|||||||
package function;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import error.LispException;
 | 
					 | 
				
			||||||
import recursion.TailCall;
 | 
					 | 
				
			||||||
import recursion.TailCalls;
 | 
					 | 
				
			||||||
import sexpression.Cons;
 | 
					 | 
				
			||||||
import sexpression.Nil;
 | 
					 | 
				
			||||||
import sexpression.SExpression;
 | 
					 | 
				
			||||||
import sexpression.Symbol;
 | 
					 | 
				
			||||||
import table.ExecutionContext;
 | 
					 | 
				
			||||||
import table.SymbolTable;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.ArrayList;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static function.builtin.EVAL.eval;
 | 
					 | 
				
			||||||
import static java.text.MessageFormat.format;
 | 
					 | 
				
			||||||
import static recursion.TailCalls.done;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class UserDefinedFunction extends LispFunction {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static final String KEYWORD_REST = "&REST";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private String name;
 | 
					 | 
				
			||||||
    private Cons body;
 | 
					 | 
				
			||||||
    private Cons lambdaExpression;
 | 
					 | 
				
			||||||
    private ExecutionContext executionContext;
 | 
					 | 
				
			||||||
    private SymbolTable functionScope;
 | 
					 | 
				
			||||||
    private ArrayList<String> formalParameters;
 | 
					 | 
				
			||||||
    private ArgumentValidator argumentValidator;
 | 
					 | 
				
			||||||
    private String keywordRestParameter;
 | 
					 | 
				
			||||||
    private boolean isKeywordRestPresent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public UserDefinedFunction(String name, Cons lambdaList, Cons body) {
 | 
					 | 
				
			||||||
        this.name = name;
 | 
					 | 
				
			||||||
        this.body = body;
 | 
					 | 
				
			||||||
        this.lambdaExpression = new Cons(new Symbol(name), new Cons(lambdaList, body));
 | 
					 | 
				
			||||||
        this.executionContext = ExecutionContext.INSTANCE;
 | 
					 | 
				
			||||||
        this.functionScope = executionContext.getScope();
 | 
					 | 
				
			||||||
        this.keywordRestParameter = null;
 | 
					 | 
				
			||||||
        this.isKeywordRestPresent = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        createFormalParameters(lambdaList);
 | 
					 | 
				
			||||||
        setupArgumentValidator();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void createFormalParameters(Cons lambdaList) {
 | 
					 | 
				
			||||||
        for (formalParameters = new ArrayList<>(); lambdaList.isCons(); lambdaList = advanceCons(lambdaList)) {
 | 
					 | 
				
			||||||
            String parameter = lambdaList.getFirst().toString();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (isKeywordRest(parameter))
 | 
					 | 
				
			||||||
                lambdaList = extractKeywordRestParameter(lambdaList);
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                formalParameters.add(parameter);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private Cons advanceCons(Cons cons) {
 | 
					 | 
				
			||||||
        return (Cons) cons.getRest();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private boolean isKeywordRest(String parameter) {
 | 
					 | 
				
			||||||
        return KEYWORD_REST.equals(parameter);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private Cons extractKeywordRestParameter(Cons lambdaList) {
 | 
					 | 
				
			||||||
        isKeywordRestPresent = true;
 | 
					 | 
				
			||||||
        lambdaList = advanceCons(lambdaList);
 | 
					 | 
				
			||||||
        keywordRestParameter = lambdaList.getFirst().toString();
 | 
					 | 
				
			||||||
        lambdaList = advanceCons(lambdaList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (containsMoreParameters(lambdaList))
 | 
					 | 
				
			||||||
            throw new IllegalKeywordRestPositionException(this.name, lambdaList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return lambdaList;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private boolean containsMoreParameters(Cons lambdaList) {
 | 
					 | 
				
			||||||
        return lambdaList.isCons();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void setupArgumentValidator() {
 | 
					 | 
				
			||||||
        argumentValidator = new ArgumentValidator(this.name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (isKeywordRestPresent)
 | 
					 | 
				
			||||||
            argumentValidator.setMinimumNumberOfArguments(this.formalParameters.size());
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            argumentValidator.setExactNumberOfArguments(this.formalParameters.size());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public SExpression call(Cons argumentList) {
 | 
					 | 
				
			||||||
        executionContext.pushFunctionCall(this);
 | 
					 | 
				
			||||||
        SExpression result = callTailRecursive(argumentList).invoke();
 | 
					 | 
				
			||||||
        executionContext.popFunctionCall();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return result;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private TailCall<SExpression> callTailRecursive(Cons argumentList) {
 | 
					 | 
				
			||||||
        argumentValidator.validate(argumentList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        SExpression result = evaluateInFunctionScope(argumentList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (executionContext.isRecur()) {
 | 
					 | 
				
			||||||
            executionContext.clearRecur();
 | 
					 | 
				
			||||||
            return TailCalls.tailCall(() -> callTailRecursive((Cons) result));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return done(result);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private SExpression evaluateInFunctionScope(Cons argumentList) {
 | 
					 | 
				
			||||||
        SymbolTable callingScope = executionContext.getScope();
 | 
					 | 
				
			||||||
        SymbolTable executionScope = bindParameterValuesToFunctionScope(argumentList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        executionContext.setScope(executionScope);
 | 
					 | 
				
			||||||
        SExpression lastEvaluation = evaluateBody();
 | 
					 | 
				
			||||||
        executionContext.setScope(callingScope);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return lastEvaluation;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private SymbolTable bindParameterValuesToFunctionScope(Cons argumentList) {
 | 
					 | 
				
			||||||
        SymbolTable executionScope = new SymbolTable(functionScope);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (String parameter : formalParameters) {
 | 
					 | 
				
			||||||
            SExpression currentArg = argumentList.getFirst();
 | 
					 | 
				
			||||||
            executionScope.set(parameter, currentArg);
 | 
					 | 
				
			||||||
            argumentList = (Cons) argumentList.getRest();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (isKeywordRestPresent)
 | 
					 | 
				
			||||||
            executionScope.set(keywordRestParameter, argumentList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return executionScope;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private SExpression evaluateBody() {
 | 
					 | 
				
			||||||
        SExpression lastEvaluation = Nil.INSTANCE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (Cons expression = body; expression.isCons(); expression = (Cons) expression.getRest())
 | 
					 | 
				
			||||||
            lastEvaluation = eval(expression.getFirst());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return lastEvaluation;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public Cons getLambdaExpression() {
 | 
					 | 
				
			||||||
        return lambdaExpression;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static class IllegalKeywordRestPositionException extends LispException {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private static final long serialVersionUID = 1L;
 | 
					 | 
				
			||||||
        private String functionName;
 | 
					 | 
				
			||||||
        private Cons parameters;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public IllegalKeywordRestPositionException(String functionName, Cons parameters) {
 | 
					 | 
				
			||||||
            this.functionName = functionName;
 | 
					 | 
				
			||||||
            this.parameters = parameters;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @Override
 | 
					 | 
				
			||||||
        public String getMessage() {
 | 
					 | 
				
			||||||
            return format("unexpected parameters following ''&rest'' in definition of {0}: {1}",
 | 
					 | 
				
			||||||
                          functionName,
 | 
					 | 
				
			||||||
                          parameters);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										112
									
								
								src/main/kotlin/function/UserDefinedFunction.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/main/kotlin/function/UserDefinedFunction.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					package function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import error.LispException
 | 
				
			||||||
 | 
					import function.builtin.EVAL.eval
 | 
				
			||||||
 | 
					import sexpression.Cons
 | 
				
			||||||
 | 
					import sexpression.Nil
 | 
				
			||||||
 | 
					import sexpression.SExpression
 | 
				
			||||||
 | 
					import sexpression.Symbol
 | 
				
			||||||
 | 
					import table.ExecutionContext
 | 
				
			||||||
 | 
					import table.SymbolTable
 | 
				
			||||||
 | 
					import java.text.MessageFormat.format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					open class UserDefinedFunction(private val name: String, lambdaList: Cons, private val body: Cons) : LispFunction() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val lambdaExpression = Cons(Symbol(name), Cons(lambdaList, body))
 | 
				
			||||||
 | 
					    private val functionScope = ExecutionContext.scope
 | 
				
			||||||
 | 
					    private var formalParameters = mutableListOf<String>()
 | 
				
			||||||
 | 
					    private var argumentValidator = ArgumentValidator(name)
 | 
				
			||||||
 | 
					    private var keywordRestParameter = ""
 | 
				
			||||||
 | 
					    private var isKeywordRestPresent = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    init {
 | 
				
			||||||
 | 
					        createFormalParameters(lambdaList)
 | 
				
			||||||
 | 
					        setupArgumentValidator()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun createFormalParameters(lambdaList: Cons) = lambdaList.forEach {
 | 
				
			||||||
 | 
					        val parameter = it.first.toString()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        when {
 | 
				
			||||||
 | 
					            isKeywordRestPresent      -> setupKeywordRestParameter(parameter, it)
 | 
				
			||||||
 | 
					            KEYWORD_REST == parameter -> isKeywordRestPresent = true
 | 
				
			||||||
 | 
					            else                      -> formalParameters.add(parameter)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun setupKeywordRestParameter(parameter: String, lambdaList: Cons) {
 | 
				
			||||||
 | 
					        if (keywordRestParameter.isNotBlank())
 | 
				
			||||||
 | 
					            throw IllegalKeywordRestPositionException(name, lambdaList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        keywordRestParameter = parameter
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun setupArgumentValidator() {
 | 
				
			||||||
 | 
					        if (isKeywordRestPresent)
 | 
				
			||||||
 | 
					            argumentValidator.setMinimumNumberOfArguments(formalParameters.size)
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            argumentValidator.setExactNumberOfArguments(formalParameters.size)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun call(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
					        ExecutionContext.pushFunctionCall(this)
 | 
				
			||||||
 | 
					        val result = callTailRecursive(argumentList)
 | 
				
			||||||
 | 
					        ExecutionContext.popFunctionCall()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private tailrec fun callTailRecursive(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
					        argumentValidator.validate(argumentList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val result = evaluateInFunctionScope(argumentList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (ExecutionContext.isRecur) {
 | 
				
			||||||
 | 
					            ExecutionContext.clearRecur()
 | 
				
			||||||
 | 
					            return callTailRecursive(result as Cons)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun evaluateInFunctionScope(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
					        val callingScope = ExecutionContext.scope
 | 
				
			||||||
 | 
					        val executionScope = bindParameterValuesToFunctionScope(argumentList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ExecutionContext.scope = executionScope
 | 
				
			||||||
 | 
					        val lastEvaluation = evaluateBody()
 | 
				
			||||||
 | 
					        ExecutionContext.scope = callingScope
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return lastEvaluation
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun bindParameterValuesToFunctionScope(argumentList: Cons): SymbolTable {
 | 
				
			||||||
 | 
					        var arguments = argumentList
 | 
				
			||||||
 | 
					        val executionScope = SymbolTable(functionScope)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (parameter in formalParameters) {
 | 
				
			||||||
 | 
					            val currentArg = arguments.first
 | 
				
			||||||
 | 
					            executionScope[parameter] = currentArg
 | 
				
			||||||
 | 
					            arguments = arguments.rest as Cons
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (isKeywordRestPresent)
 | 
				
			||||||
 | 
					            executionScope[keywordRestParameter] = arguments
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return executionScope
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun evaluateBody() = body.fold(Nil as SExpression) { _, cons -> eval(cons.first) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class IllegalKeywordRestPositionException(private val functionName: String,
 | 
				
			||||||
 | 
					                                              private val parameters: Cons) : LispException() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override val message: String by lazy {
 | 
				
			||||||
 | 
					            format("unexpected parameters following ''&rest'' in definition of {0}: {1}", functionName, parameters)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    companion object {
 | 
				
			||||||
 | 
					        private const val KEYWORD_REST = "&REST"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -11,10 +11,8 @@ import sexpression.SExpression
 | 
				
			|||||||
@FunctionNames("EXIT")
 | 
					@FunctionNames("EXIT")
 | 
				
			||||||
class Exit(name: String) : LispFunction() {
 | 
					class Exit(name: String) : LispFunction() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private val argumentValidator: ArgumentValidator = ArgumentValidator(name)
 | 
					    private val argumentValidator: ArgumentValidator = ArgumentValidator(name).apply {
 | 
				
			||||||
 | 
					        setMaximumNumberOfArguments(0)
 | 
				
			||||||
    init {
 | 
					 | 
				
			||||||
        this.argumentValidator.setMaximumNumberOfArguments(0)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun call(argumentList: Cons): SExpression {
 | 
					    override fun call(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
				
			|||||||
@ -12,11 +12,9 @@ import sexpression.Symbol.Companion.T
 | 
				
			|||||||
@FunctionNames("=")
 | 
					@FunctionNames("=")
 | 
				
			||||||
class NumericEqual(name: String) : LispFunction() {
 | 
					class NumericEqual(name: String) : LispFunction() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private val argumentValidator: ArgumentValidator = ArgumentValidator(name)
 | 
					    private val argumentValidator: ArgumentValidator = ArgumentValidator(name).apply {
 | 
				
			||||||
 | 
					        setMinimumNumberOfArguments(1)
 | 
				
			||||||
    init {
 | 
					        setEveryArgumentExpectedType(LispNumber::class.java)
 | 
				
			||||||
        this.argumentValidator.setMinimumNumberOfArguments(1)
 | 
					 | 
				
			||||||
        this.argumentValidator.setEveryArgumentExpectedType(LispNumber::class.java)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun call(argumentList: Cons): SExpression {
 | 
					    override fun call(argumentList: Cons): SExpression {
 | 
				
			||||||
 | 
				
			|||||||
@ -13,13 +13,13 @@ import sexpression.Symbol
 | 
				
			|||||||
@FunctionNames("LAMBDA", "Λ")
 | 
					@FunctionNames("LAMBDA", "Λ")
 | 
				
			||||||
class Lambda(name: String) : LispSpecialFunction() {
 | 
					class Lambda(name: String) : LispSpecialFunction() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private val argumentValidator: ArgumentValidator = ArgumentValidator(name)
 | 
					    private val argumentValidator: ArgumentValidator = ArgumentValidator(name).apply {
 | 
				
			||||||
    private val lambdaListValidator: ArgumentValidator = ArgumentValidator("$name|lambda-list|")
 | 
					        setFirstArgumentExpectedType(Cons::class.java)
 | 
				
			||||||
 | 
					        setMinimumNumberOfArguments(1)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    init {
 | 
					    private val lambdaListValidator: ArgumentValidator = ArgumentValidator("$name|lambda-list|").apply {
 | 
				
			||||||
        this.argumentValidator.setFirstArgumentExpectedType(Cons::class.java)
 | 
					        setEveryArgumentExpectedType(Symbol::class.java)
 | 
				
			||||||
        this.argumentValidator.setMinimumNumberOfArguments(1)
 | 
					 | 
				
			||||||
        this.lambdaListValidator.setEveryArgumentExpectedType(Symbol::class.java)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun call(argumentList: Cons): LambdaExpression {
 | 
					    override fun call(argumentList: Cons): LambdaExpression {
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ import sexpression.SExpression
 | 
				
			|||||||
import sexpression.Symbol
 | 
					import sexpression.Symbol
 | 
				
			||||||
import kotlin.collections.Map.Entry
 | 
					import kotlin.collections.Map.Entry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
open class SymbolTable @JvmOverloads constructor(open val parent: SymbolTable? = NullSymbolTable) : Iterable<SymbolTable> {
 | 
					open class SymbolTable(open val parent: SymbolTable? = NullSymbolTable) : Iterable<SymbolTable> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private val table = mutableMapOf<String, SExpression>()
 | 
					    private val table = mutableMapOf<String, SExpression>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user