-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Exportable functions, common frontend, and scoped imports.
- Loading branch information
Showing
20 changed files
with
336 additions
and
163 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
import "module.pork" | ||
|
||
func main() { | ||
export func main() { | ||
hello() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
func hello() { | ||
export func hello() { | ||
println("Hello World") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
func main() { | ||
export func main() { | ||
three = 3 | ||
two = 2 | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
src/main/kotlin/gay/pizza/pork/ast/nodes/DefinitionModifiers.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package gay.pizza.pork.ast.nodes | ||
|
||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
class DefinitionModifiers( | ||
var export: Boolean | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
package gay.pizza.pork.cli | ||
|
||
import gay.pizza.pork.frontend.ContentSource | ||
import gay.pizza.pork.frontend.FsContentSource | ||
import gay.pizza.pork.parse.CharSource | ||
import gay.pizza.pork.parse.StringCharSource | ||
import java.nio.file.Path | ||
import kotlin.io.path.readText | ||
|
||
class FileTool(val path: Path) : Tool() { | ||
override fun createCharSource(): CharSource = StringCharSource(path.readText()) | ||
override fun resolveImportSource(path: String): CharSource = | ||
StringCharSource(this.path.parent.resolve(path).readText()) | ||
override fun createContentSource(): ContentSource = FsContentSource(path.parent) | ||
override fun rootFilePath(): String = path.fileName.toString() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package gay.pizza.pork.eval | ||
|
||
import gay.pizza.pork.ast.nodes.CompilationUnit | ||
import gay.pizza.pork.ast.nodes.ImportDeclaration | ||
|
||
class EvaluationContext( | ||
val compilationUnit: CompilationUnit, | ||
val evaluationContextProvider: EvaluationContextProvider, | ||
rootScope: Scope | ||
) { | ||
val internalScope = rootScope.fork() | ||
val externalScope = rootScope.fork() | ||
|
||
private val evaluationVisitor = EvaluationVisitor(internalScope) | ||
|
||
fun setup() { | ||
val imports = compilationUnit.declarations.filterIsInstance<ImportDeclaration>() | ||
for (import in imports) { | ||
val evaluationContext = evaluationContextProvider.provideEvaluationContext(import.path.text) | ||
internalScope.inherit(evaluationContext.externalScope) | ||
} | ||
|
||
for (definition in compilationUnit.definitions) { | ||
evaluationVisitor.visit(definition) | ||
if (definition.modifiers.export) { | ||
externalScope.define(definition.symbol.id, internalScope.value(definition.symbol.id)) | ||
} | ||
} | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/kotlin/gay/pizza/pork/eval/EvaluationContextProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package gay.pizza.pork.eval | ||
|
||
interface EvaluationContextProvider { | ||
fun provideEvaluationContext(path: String): EvaluationContext | ||
} |
143 changes: 143 additions & 0 deletions
143
src/main/kotlin/gay/pizza/pork/eval/EvaluationVisitor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package gay.pizza.pork.eval | ||
|
||
import gay.pizza.pork.ast.NodeVisitor | ||
import gay.pizza.pork.ast.nodes.* | ||
|
||
class EvaluationVisitor(val root: Scope) : NodeVisitor<Any> { | ||
private var currentScope: Scope = root | ||
|
||
override fun visitIntLiteral(node: IntLiteral): Any = node.value | ||
override fun visitStringLiteral(node: StringLiteral): Any = node.text | ||
override fun visitBooleanLiteral(node: BooleanLiteral): Any = node.value | ||
override fun visitListLiteral(node: ListLiteral): Any = node.items.map { visit(it) } | ||
|
||
override fun visitSymbol(node: Symbol): Any = None | ||
|
||
override fun visitFunctionCall(node: FunctionCall): Any { | ||
val arguments = node.arguments.map { visit(it) } | ||
return currentScope.call(node.symbol.id, Arguments(arguments)) | ||
} | ||
|
||
override fun visitDefine(node: Assignment): Any { | ||
val value = visit(node.value) | ||
currentScope.define(node.symbol.id, value) | ||
return value | ||
} | ||
|
||
override fun visitSymbolReference(node: SymbolReference): Any = | ||
currentScope.value(node.symbol.id) | ||
|
||
override fun visitLambda(node: Lambda): CallableFunction { | ||
return CallableFunction { arguments -> | ||
currentScope = currentScope.fork() | ||
for ((index, argumentSymbol) in node.arguments.withIndex()) { | ||
currentScope.define(argumentSymbol.id, arguments.values[index]) | ||
} | ||
try { | ||
var value: Any? = null | ||
for (expression in node.expressions) { | ||
value = visit(expression) | ||
} | ||
value ?: None | ||
} finally { | ||
currentScope = currentScope.leave() | ||
} | ||
} | ||
} | ||
|
||
override fun visitParentheses(node: Parentheses): Any = visit(node.expression) | ||
|
||
override fun visitPrefixOperation(node: PrefixOperation): Any { | ||
val value = visit(node.expression) | ||
return when (node.op) { | ||
PrefixOperator.Negate -> { | ||
if (value !is Boolean) { | ||
throw RuntimeException("Cannot negate a value which is not a boolean.") | ||
} | ||
!value | ||
} | ||
} | ||
} | ||
|
||
override fun visitIf(node: If): Any { | ||
val condition = visit(node.condition) | ||
return if (condition == true) { | ||
visit(node.thenExpression) | ||
} else { | ||
if (node.elseExpression != null) { | ||
visit(node.elseExpression) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
|
||
override fun visitInfixOperation(node: InfixOperation): Any { | ||
val left = visit(node.left) | ||
val right = visit(node.right) | ||
|
||
when (node.op) { | ||
InfixOperator.Equals -> { | ||
return left == right | ||
} | ||
InfixOperator.NotEquals -> { | ||
return left != right | ||
} | ||
else -> {} | ||
} | ||
|
||
if (left !is Number || right !is Number) { | ||
throw RuntimeException("Failed to evaluate infix operation, bad types.") | ||
} | ||
|
||
val leftInt = left.toInt() | ||
val rightInt = right.toInt() | ||
|
||
return when (node.op) { | ||
InfixOperator.Plus -> leftInt + rightInt | ||
InfixOperator.Minus -> leftInt - rightInt | ||
InfixOperator.Multiply -> leftInt * rightInt | ||
InfixOperator.Divide -> leftInt / rightInt | ||
else -> throw RuntimeException("Unable to handle operation ${node.op}") | ||
} | ||
} | ||
|
||
override fun visitFunctionDeclaration(node: FunctionDefinition): Any { | ||
val blockFunction = visitBlock(node.block) as BlockFunction | ||
val function = CallableFunction { arguments -> | ||
currentScope = currentScope.fork() | ||
for ((index, argumentSymbol) in node.arguments.withIndex()) { | ||
currentScope.define(argumentSymbol.id, arguments.values[index]) | ||
} | ||
try { | ||
return@CallableFunction blockFunction.call() | ||
} finally { | ||
currentScope = currentScope.leave() | ||
} | ||
} | ||
currentScope.define(node.symbol.id, function) | ||
return None | ||
} | ||
|
||
override fun visitBlock(node: Block): Any = BlockFunction { | ||
var value: Any? = null | ||
for (expression in node.expressions) { | ||
value = visit(expression) | ||
} | ||
value ?: None | ||
} | ||
|
||
override fun visitImportDeclaration(node: ImportDeclaration): Any { | ||
throw RuntimeException( | ||
"Import declarations cannot be visited in an EvaluationVisitor. " + | ||
"Utilize an EvaluationContext." | ||
) | ||
} | ||
|
||
override fun visitCompilationUnit(node: CompilationUnit): Any { | ||
throw RuntimeException( | ||
"Compilation units cannot be visited in an EvaluationVisitor. " + | ||
"Utilize an EvaluationContext." | ||
) | ||
} | ||
} |
Oops, something went wrong.