mirror of
				https://github.com/GayPizzaSpecifications/pork.git
				synced 2025-11-03 17:39:38 +00:00 
			
		
		
		
	evaluator: ensure function definitions use root scope
This commit is contained in:
		@ -10,10 +10,10 @@ class EvaluationContext(
 | 
				
			|||||||
) {
 | 
					) {
 | 
				
			||||||
  private var isAlreadySetup = false
 | 
					  private var isAlreadySetup = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  val internalScope = rootScope.fork()
 | 
					  val internalRootScope = rootScope.fork()
 | 
				
			||||||
  val externalScope = rootScope.fork()
 | 
					  val externalRootScope = rootScope.fork()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private val evaluationVisitor = EvaluationVisitor(internalScope)
 | 
					  private val evaluationVisitor = EvaluationVisitor(internalRootScope)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fun setup() {
 | 
					  fun setup() {
 | 
				
			||||||
    if (isAlreadySetup) {
 | 
					    if (isAlreadySetup) {
 | 
				
			||||||
@ -23,13 +23,13 @@ class EvaluationContext(
 | 
				
			|||||||
    val imports = compilationUnit.declarations.filterIsInstance<ImportDeclaration>()
 | 
					    val imports = compilationUnit.declarations.filterIsInstance<ImportDeclaration>()
 | 
				
			||||||
    for (import in imports) {
 | 
					    for (import in imports) {
 | 
				
			||||||
      val evaluationContext = evaluationContextProvider.provideEvaluationContext(import.path.text)
 | 
					      val evaluationContext = evaluationContextProvider.provideEvaluationContext(import.path.text)
 | 
				
			||||||
      internalScope.inherit(evaluationContext.externalScope)
 | 
					      internalRootScope.inherit(evaluationContext.externalRootScope)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (definition in compilationUnit.definitions) {
 | 
					    for (definition in compilationUnit.definitions) {
 | 
				
			||||||
      evaluationVisitor.visit(definition)
 | 
					      evaluationVisitor.visit(definition)
 | 
				
			||||||
      if (definition.modifiers.export) {
 | 
					      if (definition.modifiers.export) {
 | 
				
			||||||
        externalScope.define(definition.symbol.id, internalScope.value(definition.symbol.id))
 | 
					        externalRootScope.define(definition.symbol.id, internalRootScope.value(definition.symbol.id))
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@ package gay.pizza.pork.evaluator
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import gay.pizza.pork.ast.*
 | 
					import gay.pizza.pork.ast.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
 | 
					class EvaluationVisitor(val root: Scope) : NodeVisitor<Any> {
 | 
				
			||||||
  private var currentScope: Scope = root
 | 
					  private var currentScope: Scope = root
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  override fun visitIntLiteral(node: IntLiteral): Any = node.value
 | 
					  override fun visitIntLiteral(node: IntLiteral): Any = node.value
 | 
				
			||||||
@ -104,15 +104,15 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
 | 
				
			|||||||
  override fun visitFunctionDefinition(node: FunctionDefinition): Any {
 | 
					  override fun visitFunctionDefinition(node: FunctionDefinition): Any {
 | 
				
			||||||
    val blockFunction = visitBlock(node.block) as BlockFunction
 | 
					    val blockFunction = visitBlock(node.block) as BlockFunction
 | 
				
			||||||
    val function = CallableFunction { arguments ->
 | 
					    val function = CallableFunction { arguments ->
 | 
				
			||||||
      currentScope = currentScope.fork(inheritFastCache = true)
 | 
					      val formerScope = currentScope
 | 
				
			||||||
      currentScope.fastVariableCache.put(node.symbol.id, currentScope.value(node.symbol.id))
 | 
					      currentScope = root.fork()
 | 
				
			||||||
      for ((index, argumentSymbol) in node.arguments.withIndex()) {
 | 
					      for ((index, argumentSymbol) in node.arguments.withIndex()) {
 | 
				
			||||||
        currentScope.define(argumentSymbol.id, arguments.values[index])
 | 
					        currentScope.define(argumentSymbol.id, arguments.values[index])
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        return@CallableFunction blockFunction.call()
 | 
					        return@CallableFunction blockFunction.call()
 | 
				
			||||||
      } finally {
 | 
					      } finally {
 | 
				
			||||||
        currentScope = currentScope.leave()
 | 
					        currentScope = formerScope
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    currentScope.define(node.symbol.id, function)
 | 
					    currentScope.define(node.symbol.id, function)
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ class Evaluator(val world: World, val scope: Scope) : EvaluationContextProvider
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  fun evaluate(path: String): Scope {
 | 
					  fun evaluate(path: String): Scope {
 | 
				
			||||||
    val context = provideEvaluationContext(path)
 | 
					    val context = provideEvaluationContext(path)
 | 
				
			||||||
    return context.externalScope
 | 
					    return context.externalRootScope
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  override fun provideEvaluationContext(path: String): EvaluationContext {
 | 
					  override fun provideEvaluationContext(path: String): EvaluationContext {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,15 +1,10 @@
 | 
				
			|||||||
package gay.pizza.pork.evaluator
 | 
					package gay.pizza.pork.evaluator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Scope(
 | 
					class Scope(val parent: Scope? = null, inherits: List<Scope> = emptyList()) {
 | 
				
			||||||
  val parent: Scope? = null,
 | 
					 | 
				
			||||||
  inherits: List<Scope> = emptyList(),
 | 
					 | 
				
			||||||
  val fastVariableCache: FastVariableCache = FastVariableCache()
 | 
					 | 
				
			||||||
) {
 | 
					 | 
				
			||||||
  private val inherited = inherits.toMutableList()
 | 
					  private val inherited = inherits.toMutableList()
 | 
				
			||||||
  private val variables = mutableMapOf<String, Any>()
 | 
					  private val variables = mutableMapOf<String, Any>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fun define(name: String, value: Any) {
 | 
					  fun define(name: String, value: Any) {
 | 
				
			||||||
    fastVariableCache.invalidate(name)
 | 
					 | 
				
			||||||
    if (variables.containsKey(name)) {
 | 
					    if (variables.containsKey(name)) {
 | 
				
			||||||
      throw RuntimeException("Variable '${name}' is already defined")
 | 
					      throw RuntimeException("Variable '${name}' is already defined")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -17,11 +12,6 @@ class Scope(
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fun value(name: String): Any {
 | 
					  fun value(name: String): Any {
 | 
				
			||||||
    val fastCached = fastVariableCache.lookup(name)
 | 
					 | 
				
			||||||
    if (fastCached != FastVariableCache.NotFound) {
 | 
					 | 
				
			||||||
      return fastCached
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    val value = valueOrNotFound(name)
 | 
					    val value = valueOrNotFound(name)
 | 
				
			||||||
    if (value == NotFound) {
 | 
					    if (value == NotFound) {
 | 
				
			||||||
      throw RuntimeException("Variable '${name}' not defined.")
 | 
					      throw RuntimeException("Variable '${name}' not defined.")
 | 
				
			||||||
@ -58,10 +48,8 @@ class Scope(
 | 
				
			|||||||
    return value.call(arguments)
 | 
					    return value.call(arguments)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fun fork(inheritFastCache: Boolean = false): Scope {
 | 
					  fun fork(): Scope =
 | 
				
			||||||
    val fastCache = if (inheritFastCache) fastVariableCache else FastVariableCache()
 | 
					    Scope(this)
 | 
				
			||||||
    return Scope(this, fastVariableCache = fastCache)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fun leave(): Scope {
 | 
					  fun leave(): Scope {
 | 
				
			||||||
    if (parent == null) {
 | 
					    if (parent == null) {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user