mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 05:10:55 +00:00
evaluator: ensure function definitions use root scope
This commit is contained in:
parent
725137c82f
commit
9634a735ee
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user