mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 13:11:32 +00:00
language: prelude and internal functions, and varargs support
This commit is contained in:
@ -1,9 +1,6 @@
|
||||
package gay.pizza.pork.evaluator
|
||||
|
||||
import gay.pizza.pork.ast.CompilationUnit
|
||||
import gay.pizza.pork.ast.Definition
|
||||
import gay.pizza.pork.ast.FunctionDefinition
|
||||
import gay.pizza.pork.ast.ImportDeclaration
|
||||
import gay.pizza.pork.ast.*
|
||||
import gay.pizza.pork.frontend.ImportLocator
|
||||
|
||||
class CompilationUnitContext(
|
||||
@ -45,6 +42,7 @@ class CompilationUnitContext(
|
||||
}
|
||||
|
||||
private fun processAllImports() {
|
||||
processPreludeImport()
|
||||
val imports = compilationUnit.declarations.filterIsInstance<ImportDeclaration>()
|
||||
for (import in imports) {
|
||||
processImport(import)
|
||||
@ -57,4 +55,18 @@ class CompilationUnitContext(
|
||||
val evaluationContext = evaluator.context(importLocator)
|
||||
internalScope.inherit(evaluationContext.externalScope)
|
||||
}
|
||||
|
||||
private fun processPreludeImport() {
|
||||
processImport(preludeImport)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val preludeImport = ImportDeclaration(
|
||||
Symbol("std"),
|
||||
listOf(
|
||||
Symbol("lang"),
|
||||
Symbol("prelude")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -119,8 +119,8 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
subtract = { a, b -> a - b },
|
||||
multiply = { a, b -> a * b },
|
||||
divide = { a, b -> a / b },
|
||||
euclideanModulo = { _, _ -> throw RuntimeException("Can't perform integer modulo between floating point types") },
|
||||
remainder = { _, _ -> throw RuntimeException("Can't perform integer remainder between floating point types") },
|
||||
euclideanModulo = { _, _ -> floatingPointTypeError("integer modulo") },
|
||||
remainder = { _, _ -> floatingPointTypeError("integer remainder") },
|
||||
lesser = { a, b -> a < b },
|
||||
greater = { a, b -> a > b },
|
||||
lesserEqual = { a, b -> a <= b },
|
||||
@ -138,8 +138,8 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
subtract = { a, b -> a - b },
|
||||
multiply = { a, b -> a * b },
|
||||
divide = { a, b -> a / b },
|
||||
euclideanModulo = { _, _ -> throw RuntimeException("Can't perform integer modulo between floating point types") },
|
||||
remainder = { _, _ -> throw RuntimeException("Can't perform integer remainder between floating point types") },
|
||||
euclideanModulo = { _, _ -> floatingPointTypeError("integer modulo") },
|
||||
remainder = { _, _ -> floatingPointTypeError("integer remainder") },
|
||||
lesser = { a, b -> a < b },
|
||||
greater = { a, b -> a > b },
|
||||
lesserEqual = { a, b -> a <= b },
|
||||
@ -228,31 +228,19 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
}
|
||||
|
||||
override fun visitFunctionDefinition(node: FunctionDefinition): Any {
|
||||
throw RuntimeException(
|
||||
"Function declarations cannot be visited in an EvaluationVisitor. " +
|
||||
"Utilize a FunctionContext."
|
||||
)
|
||||
topLevelUsedError("FunctionDefinition", "FunctionContext")
|
||||
}
|
||||
|
||||
override fun visitImportDeclaration(node: ImportDeclaration): Any {
|
||||
throw RuntimeException(
|
||||
"Import declarations cannot be visited in an EvaluationVisitor. " +
|
||||
"Utilize an CompilationUnitContext."
|
||||
)
|
||||
topLevelUsedError("ImportDeclaration", "CompilationUnitContext")
|
||||
}
|
||||
|
||||
override fun visitCompilationUnit(node: CompilationUnit): Any {
|
||||
throw RuntimeException(
|
||||
"Compilation units cannot be visited in an EvaluationVisitor. " +
|
||||
"Utilize an CompilationUnitContext."
|
||||
)
|
||||
topLevelUsedError("CompilationUnit", "CompilationUnitContext")
|
||||
}
|
||||
|
||||
override fun visitNative(node: Native): Any {
|
||||
throw RuntimeException(
|
||||
"Native definition cannot be visited in an EvaluationVisitor. " +
|
||||
"Utilize an FunctionContext."
|
||||
)
|
||||
topLevelUsedError("Native", "FunctionContext")
|
||||
}
|
||||
|
||||
override fun visitContinue(node: Continue): Any = ContinueMarker
|
||||
@ -266,6 +254,17 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun floatingPointTypeError(operation: String): Nothing {
|
||||
throw RuntimeException("Can't perform $operation between floating point types")
|
||||
}
|
||||
|
||||
private fun topLevelUsedError(name: String, alternative: String): Nothing {
|
||||
throw RuntimeException(
|
||||
"$name cannot be visited in an EvaluationVisitor. " +
|
||||
"Utilize an $alternative instead."
|
||||
)
|
||||
}
|
||||
|
||||
private object BreakMarker : RuntimeException("Break Marker")
|
||||
private object ContinueMarker: RuntimeException("Continue Marker")
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import gay.pizza.pork.frontend.World
|
||||
|
||||
class Evaluator(val world: World, val scope: Scope) {
|
||||
private val contexts = mutableMapOf<String, CompilationUnitContext>()
|
||||
private val nativeFunctionProviders = mutableMapOf<String, NativeFunctionProvider>()
|
||||
private val nativeProviders = mutableMapOf<String, NativeProvider>()
|
||||
|
||||
fun evaluate(locator: ImportLocator): Scope =
|
||||
context(locator).externalScope
|
||||
@ -20,12 +20,12 @@ class Evaluator(val world: World, val scope: Scope) {
|
||||
return context
|
||||
}
|
||||
|
||||
fun nativeFunctionProvider(form: String): NativeFunctionProvider {
|
||||
return nativeFunctionProviders[form] ?:
|
||||
fun nativeFunctionProvider(form: String): NativeProvider {
|
||||
return nativeProviders[form] ?:
|
||||
throw RuntimeException("Unknown native function form: $form")
|
||||
}
|
||||
|
||||
fun addNativeFunctionProvider(form: String, nativeFunctionProvider: NativeFunctionProvider) {
|
||||
nativeFunctionProviders[form] = nativeFunctionProvider
|
||||
fun addNativeProvider(form: String, nativeProvider: NativeProvider) {
|
||||
nativeProviders[form] = nativeProvider
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,14 @@ class FunctionContext(val compilationUnitContext: CompilationUnitContext, val no
|
||||
}
|
||||
|
||||
val scope = compilationUnitContext.internalScope.fork()
|
||||
for ((index, argumentSymbol) in node.arguments.withIndex()) {
|
||||
scope.define(argumentSymbol.id, arguments.values[index])
|
||||
for ((index, spec) in node.arguments.withIndex()) {
|
||||
if (spec.multiple) {
|
||||
val list = arguments.values.subList(index, arguments.values.size - 1)
|
||||
scope.define(spec.symbol.id, list)
|
||||
break
|
||||
} else {
|
||||
scope.define(spec.symbol.id, arguments.values[index])
|
||||
}
|
||||
}
|
||||
|
||||
if (node.block == null) {
|
||||
|
@ -0,0 +1,23 @@
|
||||
package gay.pizza.pork.evaluator
|
||||
|
||||
class InternalNativeProvider(val quiet: Boolean = false) : NativeProvider {
|
||||
private val functions = mutableMapOf(
|
||||
"println" to CallableFunction(::printLine)
|
||||
)
|
||||
|
||||
override fun provideNativeFunction(definition: String): CallableFunction {
|
||||
return functions[definition] ?: throw RuntimeException("Unknown Internal Function: $definition")
|
||||
}
|
||||
|
||||
private fun printLine(arguments: Arguments): Any {
|
||||
if (quiet) {
|
||||
return None
|
||||
}
|
||||
when (arguments.values.count()) {
|
||||
0 -> println()
|
||||
1 -> println(arguments.values[0])
|
||||
else -> println(arguments.values.joinToString(" "))
|
||||
}
|
||||
return None
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
package gay.pizza.pork.evaluator
|
||||
|
||||
interface NativeFunctionProvider {
|
||||
interface NativeProvider {
|
||||
fun provideNativeFunction(definition: String): CallableFunction
|
||||
}
|
Reference in New Issue
Block a user