mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-02 12:50:55 +00:00
language: prelude and internal functions, and varargs support
This commit is contained in:
parent
1cfb197a7f
commit
e8c984f2dc
10
README.md
10
README.md
@ -5,11 +5,11 @@ A work-in-progress programming language.
|
|||||||
```pork
|
```pork
|
||||||
/* fibonacci sequence */
|
/* fibonacci sequence */
|
||||||
func fib(n) {
|
func fib(n) {
|
||||||
if n == 0
|
if n < 2 {
|
||||||
then 0
|
n
|
||||||
else if n == 1
|
} else {
|
||||||
then 1
|
fib(n - 1) + fib(n - 2)
|
||||||
else fib(n - 1) + fib(n - 2)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -117,6 +117,12 @@ types:
|
|||||||
type: Symbol
|
type: Symbol
|
||||||
- name: arguments
|
- name: arguments
|
||||||
type: List<Expression>
|
type: List<Expression>
|
||||||
|
ArgumentSpec:
|
||||||
|
values:
|
||||||
|
- name: symbol
|
||||||
|
type: Symbol
|
||||||
|
- name: multiple
|
||||||
|
type: Boolean
|
||||||
FunctionDefinition:
|
FunctionDefinition:
|
||||||
parent: Definition
|
parent: Definition
|
||||||
values:
|
values:
|
||||||
@ -125,7 +131,7 @@ types:
|
|||||||
- name: symbol
|
- name: symbol
|
||||||
type: Symbol
|
type: Symbol
|
||||||
- name: arguments
|
- name: arguments
|
||||||
type: List<Symbol>
|
type: List<ArgumentSpec>
|
||||||
- name: block
|
- name: block
|
||||||
type: Block?
|
type: Block?
|
||||||
- name: native
|
- name: native
|
||||||
|
@ -14,6 +14,7 @@ digraph A {
|
|||||||
type_InfixOperation [shape=box,label="InfixOperation"]
|
type_InfixOperation [shape=box,label="InfixOperation"]
|
||||||
type_BooleanLiteral [shape=box,label="BooleanLiteral"]
|
type_BooleanLiteral [shape=box,label="BooleanLiteral"]
|
||||||
type_FunctionCall [shape=box,label="FunctionCall"]
|
type_FunctionCall [shape=box,label="FunctionCall"]
|
||||||
|
type_ArgumentSpec [shape=box,label="ArgumentSpec"]
|
||||||
type_FunctionDefinition [shape=box,label="FunctionDefinition"]
|
type_FunctionDefinition [shape=box,label="FunctionDefinition"]
|
||||||
type_If [shape=box,label="If"]
|
type_If [shape=box,label="If"]
|
||||||
type_ImportDeclaration [shape=box,label="ImportDeclaration"]
|
type_ImportDeclaration [shape=box,label="ImportDeclaration"]
|
||||||
@ -70,8 +71,10 @@ digraph A {
|
|||||||
type_InfixOperation -> type_InfixOperator [style=dotted]
|
type_InfixOperation -> type_InfixOperator [style=dotted]
|
||||||
type_FunctionCall -> type_Symbol [style=dotted]
|
type_FunctionCall -> type_Symbol [style=dotted]
|
||||||
type_FunctionCall -> type_Expression [style=dotted]
|
type_FunctionCall -> type_Expression [style=dotted]
|
||||||
|
type_ArgumentSpec -> type_Symbol [style=dotted]
|
||||||
type_FunctionDefinition -> type_DefinitionModifiers [style=dotted]
|
type_FunctionDefinition -> type_DefinitionModifiers [style=dotted]
|
||||||
type_FunctionDefinition -> type_Symbol [style=dotted]
|
type_FunctionDefinition -> type_Symbol [style=dotted]
|
||||||
|
type_FunctionDefinition -> type_ArgumentSpec [style=dotted]
|
||||||
type_FunctionDefinition -> type_Block [style=dotted]
|
type_FunctionDefinition -> type_Block [style=dotted]
|
||||||
type_FunctionDefinition -> type_Native [style=dotted]
|
type_FunctionDefinition -> type_Native [style=dotted]
|
||||||
type_If -> type_Expression [style=dotted]
|
type_If -> type_Expression [style=dotted]
|
||||||
|
9
ast/src/main/kotlin/gay/pizza/pork/ast/ArgumentSpec.kt
Normal file
9
ast/src/main/kotlin/gay/pizza/pork/ast/ArgumentSpec.kt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// GENERATED CODE FROM PORK AST CODEGEN
|
||||||
|
package gay.pizza.pork.ast
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("argumentSpec")
|
||||||
|
class ArgumentSpec(var symbol: Symbol, var multiple: Boolean)
|
@ -6,11 +6,11 @@ import kotlinx.serialization.Serializable
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("functionDefinition")
|
@SerialName("functionDefinition")
|
||||||
class FunctionDefinition(override val modifiers: DefinitionModifiers, override val symbol: Symbol, val arguments: List<Symbol>, val block: Block?, val native: Native?) : Definition() {
|
class FunctionDefinition(override val modifiers: DefinitionModifiers, override val symbol: Symbol, val arguments: List<ArgumentSpec>, val block: Block?, val native: Native?) : Definition() {
|
||||||
override val type: NodeType = NodeType.FunctionDefinition
|
override val type: NodeType = NodeType.FunctionDefinition
|
||||||
|
|
||||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||||
visitor.visitAll(listOf(symbol), arguments, listOf(block), listOf(native))
|
visitor.visitAll(listOf(symbol), listOf(block), listOf(native))
|
||||||
|
|
||||||
override fun <T> visit(visitor: NodeVisitor<T>): T =
|
override fun <T> visit(visitor: NodeVisitor<T>): T =
|
||||||
visitor.visitFunctionDefinition(this)
|
visitor.visitFunctionDefinition(this)
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
package gay.pizza.pork.evaluator
|
package gay.pizza.pork.evaluator
|
||||||
|
|
||||||
import gay.pizza.pork.ast.CompilationUnit
|
import gay.pizza.pork.ast.*
|
||||||
import gay.pizza.pork.ast.Definition
|
|
||||||
import gay.pizza.pork.ast.FunctionDefinition
|
|
||||||
import gay.pizza.pork.ast.ImportDeclaration
|
|
||||||
import gay.pizza.pork.frontend.ImportLocator
|
import gay.pizza.pork.frontend.ImportLocator
|
||||||
|
|
||||||
class CompilationUnitContext(
|
class CompilationUnitContext(
|
||||||
@ -45,6 +42,7 @@ class CompilationUnitContext(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun processAllImports() {
|
private fun processAllImports() {
|
||||||
|
processPreludeImport()
|
||||||
val imports = compilationUnit.declarations.filterIsInstance<ImportDeclaration>()
|
val imports = compilationUnit.declarations.filterIsInstance<ImportDeclaration>()
|
||||||
for (import in imports) {
|
for (import in imports) {
|
||||||
processImport(import)
|
processImport(import)
|
||||||
@ -57,4 +55,18 @@ class CompilationUnitContext(
|
|||||||
val evaluationContext = evaluator.context(importLocator)
|
val evaluationContext = evaluator.context(importLocator)
|
||||||
internalScope.inherit(evaluationContext.externalScope)
|
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 },
|
subtract = { a, b -> a - b },
|
||||||
multiply = { a, b -> a * b },
|
multiply = { a, b -> a * b },
|
||||||
divide = { a, b -> a / b },
|
divide = { a, b -> a / b },
|
||||||
euclideanModulo = { _, _ -> throw RuntimeException("Can't perform integer modulo between floating point types") },
|
euclideanModulo = { _, _ -> floatingPointTypeError("integer modulo") },
|
||||||
remainder = { _, _ -> throw RuntimeException("Can't perform integer remainder between floating point types") },
|
remainder = { _, _ -> floatingPointTypeError("integer remainder") },
|
||||||
lesser = { a, b -> a < b },
|
lesser = { a, b -> a < b },
|
||||||
greater = { a, b -> a > b },
|
greater = { a, b -> a > b },
|
||||||
lesserEqual = { a, b -> a <= b },
|
lesserEqual = { a, b -> a <= b },
|
||||||
@ -138,8 +138,8 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
subtract = { a, b -> a - b },
|
subtract = { a, b -> a - b },
|
||||||
multiply = { a, b -> a * b },
|
multiply = { a, b -> a * b },
|
||||||
divide = { a, b -> a / b },
|
divide = { a, b -> a / b },
|
||||||
euclideanModulo = { _, _ -> throw RuntimeException("Can't perform integer modulo between floating point types") },
|
euclideanModulo = { _, _ -> floatingPointTypeError("integer modulo") },
|
||||||
remainder = { _, _ -> throw RuntimeException("Can't perform integer remainder between floating point types") },
|
remainder = { _, _ -> floatingPointTypeError("integer remainder") },
|
||||||
lesser = { a, b -> a < b },
|
lesser = { a, b -> a < b },
|
||||||
greater = { a, b -> a > b },
|
greater = { a, b -> a > b },
|
||||||
lesserEqual = { 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 {
|
override fun visitFunctionDefinition(node: FunctionDefinition): Any {
|
||||||
throw RuntimeException(
|
topLevelUsedError("FunctionDefinition", "FunctionContext")
|
||||||
"Function declarations cannot be visited in an EvaluationVisitor. " +
|
|
||||||
"Utilize a FunctionContext."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitImportDeclaration(node: ImportDeclaration): Any {
|
override fun visitImportDeclaration(node: ImportDeclaration): Any {
|
||||||
throw RuntimeException(
|
topLevelUsedError("ImportDeclaration", "CompilationUnitContext")
|
||||||
"Import declarations cannot be visited in an EvaluationVisitor. " +
|
|
||||||
"Utilize an CompilationUnitContext."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCompilationUnit(node: CompilationUnit): Any {
|
override fun visitCompilationUnit(node: CompilationUnit): Any {
|
||||||
throw RuntimeException(
|
topLevelUsedError("CompilationUnit", "CompilationUnitContext")
|
||||||
"Compilation units cannot be visited in an EvaluationVisitor. " +
|
|
||||||
"Utilize an CompilationUnitContext."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitNative(node: Native): Any {
|
override fun visitNative(node: Native): Any {
|
||||||
throw RuntimeException(
|
topLevelUsedError("Native", "FunctionContext")
|
||||||
"Native definition cannot be visited in an EvaluationVisitor. " +
|
|
||||||
"Utilize an FunctionContext."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitContinue(node: Continue): Any = ContinueMarker
|
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 BreakMarker : RuntimeException("Break Marker")
|
||||||
private object ContinueMarker: RuntimeException("Continue 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) {
|
class Evaluator(val world: World, val scope: Scope) {
|
||||||
private val contexts = mutableMapOf<String, CompilationUnitContext>()
|
private val contexts = mutableMapOf<String, CompilationUnitContext>()
|
||||||
private val nativeFunctionProviders = mutableMapOf<String, NativeFunctionProvider>()
|
private val nativeProviders = mutableMapOf<String, NativeProvider>()
|
||||||
|
|
||||||
fun evaluate(locator: ImportLocator): Scope =
|
fun evaluate(locator: ImportLocator): Scope =
|
||||||
context(locator).externalScope
|
context(locator).externalScope
|
||||||
@ -20,12 +20,12 @@ class Evaluator(val world: World, val scope: Scope) {
|
|||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
fun nativeFunctionProvider(form: String): NativeFunctionProvider {
|
fun nativeFunctionProvider(form: String): NativeProvider {
|
||||||
return nativeFunctionProviders[form] ?:
|
return nativeProviders[form] ?:
|
||||||
throw RuntimeException("Unknown native function form: $form")
|
throw RuntimeException("Unknown native function form: $form")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addNativeFunctionProvider(form: String, nativeFunctionProvider: NativeFunctionProvider) {
|
fun addNativeProvider(form: String, nativeProvider: NativeProvider) {
|
||||||
nativeFunctionProviders[form] = nativeFunctionProvider
|
nativeProviders[form] = nativeProvider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,14 @@ class FunctionContext(val compilationUnitContext: CompilationUnitContext, val no
|
|||||||
}
|
}
|
||||||
|
|
||||||
val scope = compilationUnitContext.internalScope.fork()
|
val scope = compilationUnitContext.internalScope.fork()
|
||||||
for ((index, argumentSymbol) in node.arguments.withIndex()) {
|
for ((index, spec) in node.arguments.withIndex()) {
|
||||||
scope.define(argumentSymbol.id, arguments.values[index])
|
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) {
|
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
|
package gay.pizza.pork.evaluator
|
||||||
|
|
||||||
interface NativeFunctionProvider {
|
interface NativeProvider {
|
||||||
fun provideNativeFunction(definition: String): CallableFunction
|
fun provideNativeFunction(definition: String): CallableFunction
|
||||||
}
|
}
|
@ -1,17 +1,13 @@
|
|||||||
/* fibonacci sequence */
|
/* fibonacci sequence */
|
||||||
func fib(n) {
|
func fib(n) {
|
||||||
if n == 0 {
|
if n < 2 {
|
||||||
0
|
n
|
||||||
} else {
|
} else {
|
||||||
if n == 1 {
|
fib(n - 1) + fib(n - 2)
|
||||||
1
|
|
||||||
} else {
|
|
||||||
fib(n - 1) + fib(n - 2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export func main() {
|
export func main() {
|
||||||
let result = fib(20)
|
let result = fib(30)
|
||||||
println(result)
|
println(result)
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
package gay.pizza.pork.ffi
|
package gay.pizza.pork.ffi
|
||||||
|
|
||||||
import gay.pizza.pork.ast.CompilationUnit
|
import gay.pizza.pork.ast.*
|
||||||
import gay.pizza.pork.ast.DefinitionModifiers
|
|
||||||
import gay.pizza.pork.ast.FunctionDefinition
|
|
||||||
import gay.pizza.pork.ast.Native
|
|
||||||
import gay.pizza.pork.ast.StringLiteral
|
|
||||||
import gay.pizza.pork.ast.Symbol
|
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
import java.lang.reflect.Parameter
|
import java.lang.reflect.Parameter
|
||||||
@ -149,7 +144,12 @@ class JavaAutogen(val javaClass: Class<*>) {
|
|||||||
FunctionDefinition(
|
FunctionDefinition(
|
||||||
modifiers = DefinitionModifiers(true),
|
modifiers = DefinitionModifiers(true),
|
||||||
symbol = Symbol("${prefix}_${name}"),
|
symbol = Symbol("${prefix}_${name}"),
|
||||||
arguments = parameterNames.map { Symbol(it) },
|
arguments = parameterNames.map {
|
||||||
|
ArgumentSpec(
|
||||||
|
symbol = Symbol(it),
|
||||||
|
multiple = false
|
||||||
|
)
|
||||||
|
},
|
||||||
native = asNative(functionDefinition),
|
native = asNative(functionDefinition),
|
||||||
block = null
|
block = null
|
||||||
)
|
)
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package gay.pizza.pork.ffi
|
package gay.pizza.pork.ffi
|
||||||
|
|
||||||
import gay.pizza.pork.evaluator.CallableFunction
|
import gay.pizza.pork.evaluator.CallableFunction
|
||||||
import gay.pizza.pork.evaluator.NativeFunctionProvider
|
import gay.pizza.pork.evaluator.NativeProvider
|
||||||
import gay.pizza.pork.evaluator.None
|
import gay.pizza.pork.evaluator.None
|
||||||
import java.lang.invoke.MethodHandles
|
import java.lang.invoke.MethodHandles
|
||||||
import java.lang.invoke.MethodType
|
import java.lang.invoke.MethodType
|
||||||
|
|
||||||
class JavaNativeProvider : NativeFunctionProvider {
|
class JavaNativeProvider : NativeProvider {
|
||||||
private val lookup = MethodHandles.lookup()
|
private val lookup = MethodHandles.lookup()
|
||||||
|
|
||||||
override fun provideNativeFunction(definition: String): CallableFunction {
|
override fun provideNativeFunction(definition: String): CallableFunction {
|
||||||
|
@ -2,9 +2,9 @@ package gay.pizza.pork.ffi
|
|||||||
|
|
||||||
import com.sun.jna.Function
|
import com.sun.jna.Function
|
||||||
import gay.pizza.pork.evaluator.CallableFunction
|
import gay.pizza.pork.evaluator.CallableFunction
|
||||||
import gay.pizza.pork.evaluator.NativeFunctionProvider
|
import gay.pizza.pork.evaluator.NativeProvider
|
||||||
|
|
||||||
class JnaNativeProvider : NativeFunctionProvider {
|
class JnaNativeProvider : NativeProvider {
|
||||||
override fun provideNativeFunction(definition: String): CallableFunction {
|
override fun provideNativeFunction(definition: String): CallableFunction {
|
||||||
val functionDefinition = FfiFunctionDefinition.parse(definition)
|
val functionDefinition = FfiFunctionDefinition.parse(definition)
|
||||||
val function = Function.getFunction(functionDefinition.library, functionDefinition.function)
|
val function = Function.getFunction(functionDefinition.library, functionDefinition.function)
|
||||||
|
@ -217,7 +217,7 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
private fun readImportDeclaration(): ImportDeclaration = within {
|
private fun readImportDeclaration(): ImportDeclaration = within {
|
||||||
expect(TokenType.Import)
|
expect(TokenType.Import)
|
||||||
val form = readSymbolRaw()
|
val form = readSymbolRaw()
|
||||||
val components = oneAndContinuedBy(TokenType.Period) { readSymbolRaw() }
|
val components = oneAndContinuedBy(TokenType.Dot) { readSymbolRaw() }
|
||||||
ImportDeclaration(form, components)
|
ImportDeclaration(form, components)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +237,12 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
val name = readSymbolRaw()
|
val name = readSymbolRaw()
|
||||||
expect(TokenType.LeftParentheses)
|
expect(TokenType.LeftParentheses)
|
||||||
val arguments = collect(TokenType.RightParentheses, TokenType.Comma) {
|
val arguments = collect(TokenType.RightParentheses, TokenType.Comma) {
|
||||||
readSymbolRaw()
|
val symbol = readSymbolRaw()
|
||||||
|
var multiple: Boolean = false
|
||||||
|
if (next(TokenType.DotDotDot)) {
|
||||||
|
multiple = true
|
||||||
|
}
|
||||||
|
ArgumentSpec(symbol, multiple)
|
||||||
}
|
}
|
||||||
expect(TokenType.RightParentheses)
|
expect(TokenType.RightParentheses)
|
||||||
|
|
||||||
|
@ -155,7 +155,10 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
|
|||||||
visit(node.symbol)
|
visit(node.symbol)
|
||||||
append("(")
|
append("(")
|
||||||
for ((index, argument) in node.arguments.withIndex()) {
|
for ((index, argument) in node.arguments.withIndex()) {
|
||||||
visit(argument)
|
visit(argument.symbol)
|
||||||
|
if (argument.multiple) {
|
||||||
|
append("...")
|
||||||
|
}
|
||||||
if (index + 1 != node.arguments.size) {
|
if (index + 1 != node.arguments.size) {
|
||||||
append(", ")
|
append(", ")
|
||||||
}
|
}
|
||||||
|
@ -30,23 +30,25 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
|||||||
LeftParentheses(SingleChar('(')),
|
LeftParentheses(SingleChar('(')),
|
||||||
RightParentheses(SingleChar(')')),
|
RightParentheses(SingleChar(')')),
|
||||||
Negation(SingleChar('!'), Promotion('=', Inequality), OperatorFamily),
|
Negation(SingleChar('!'), Promotion('=', Inequality), OperatorFamily),
|
||||||
Mod(Keyword("mod"), OperatorFamily),
|
Mod(ManyChars("mod"), OperatorFamily),
|
||||||
Rem(Keyword("rem"), OperatorFamily),
|
Rem(ManyChars("rem"), OperatorFamily),
|
||||||
Comma(SingleChar(',')),
|
Comma(SingleChar(',')),
|
||||||
Period(SingleChar('.')),
|
DotDotDot(ManyChars("...")),
|
||||||
False(Keyword("false"), KeywordFamily),
|
DotDot(ManyChars(".."), Promotion('.', DotDotDot)),
|
||||||
True(Keyword("true"), KeywordFamily),
|
Dot(SingleChar('.'), Promotion('.', DotDot)),
|
||||||
If(Keyword("if"), KeywordFamily),
|
False(ManyChars("false"), KeywordFamily),
|
||||||
Else(Keyword("else"), KeywordFamily),
|
True(ManyChars("true"), KeywordFamily),
|
||||||
While(Keyword("while"), KeywordFamily),
|
If(ManyChars("if"), KeywordFamily),
|
||||||
Continue(Keyword("continue"), KeywordFamily),
|
Else(ManyChars("else"), KeywordFamily),
|
||||||
Break(Keyword("break"), KeywordFamily),
|
While(ManyChars("while"), KeywordFamily),
|
||||||
Import(Keyword("import"), KeywordFamily),
|
Continue(ManyChars("continue"), KeywordFamily),
|
||||||
Export(Keyword("export"), KeywordFamily),
|
Break(ManyChars("break"), KeywordFamily),
|
||||||
Func(Keyword("func"), KeywordFamily),
|
Import(ManyChars("import"), KeywordFamily),
|
||||||
Native(Keyword("native"), KeywordFamily),
|
Export(ManyChars("export"), KeywordFamily),
|
||||||
Let(Keyword("let"), KeywordFamily),
|
Func(ManyChars("func"), KeywordFamily),
|
||||||
Var(Keyword("var"), KeywordFamily),
|
Native(ManyChars("native"), KeywordFamily),
|
||||||
|
Let(ManyChars("let"), KeywordFamily),
|
||||||
|
Var(ManyChars("var"), KeywordFamily),
|
||||||
Whitespace(CharConsumer { it == ' ' || it == '\r' || it == '\n' || it == '\t' }),
|
Whitespace(CharConsumer { it == ' ' || it == '\r' || it == '\n' || it == '\t' }),
|
||||||
BlockComment(CommentFamily),
|
BlockComment(CommentFamily),
|
||||||
LineComment(CommentFamily),
|
LineComment(CommentFamily),
|
||||||
@ -54,8 +56,8 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
|||||||
|
|
||||||
val promotions: List<Promotion> =
|
val promotions: List<Promotion> =
|
||||||
properties.filterIsInstance<Promotion>()
|
properties.filterIsInstance<Promotion>()
|
||||||
val keyword: Keyword? =
|
val manyChars: ManyChars? =
|
||||||
properties.filterIsInstance<Keyword>().singleOrNull()
|
properties.filterIsInstance<ManyChars>().singleOrNull()
|
||||||
val singleChar: SingleChar? =
|
val singleChar: SingleChar? =
|
||||||
properties.filterIsInstance<SingleChar>().singleOrNull()
|
properties.filterIsInstance<SingleChar>().singleOrNull()
|
||||||
val family: TokenFamily =
|
val family: TokenFamily =
|
||||||
@ -67,7 +69,7 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
|||||||
properties.filterIsInstance<TokenUpgrader>().singleOrNull()
|
properties.filterIsInstance<TokenUpgrader>().singleOrNull()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val Keywords = entries.filter { item -> item.keyword != null }
|
val ManyChars = entries.filter { item -> item.manyChars != null }
|
||||||
val SingleChars = entries.filter { item -> item.singleChar != null }
|
val SingleChars = entries.filter { item -> item.singleChar != null }
|
||||||
val CharConsumers = entries.filter { item ->
|
val CharConsumers = entries.filter { item ->
|
||||||
item.charConsumer != null || item.charIndexConsumer != null }
|
item.charConsumer != null || item.charIndexConsumer != null }
|
||||||
|
@ -3,15 +3,15 @@ package gay.pizza.pork.parser
|
|||||||
interface TokenTypeProperty {
|
interface TokenTypeProperty {
|
||||||
class SingleChar(val char: Char) : TokenTypeProperty
|
class SingleChar(val char: Char) : TokenTypeProperty
|
||||||
class Promotion(val nextChar: Char, val type: TokenType) : TokenTypeProperty
|
class Promotion(val nextChar: Char, val type: TokenType) : TokenTypeProperty
|
||||||
class Keyword(val text: String) : TokenTypeProperty
|
class ManyChars(val text: String) : TokenTypeProperty
|
||||||
class CharConsumer(val isValid: (Char) -> Boolean) : TokenTypeProperty
|
class CharConsumer(val isValid: (Char) -> Boolean) : TokenTypeProperty
|
||||||
class CharIndexConsumer(val isValid: (Char, Int) -> Boolean) : TokenTypeProperty
|
class CharIndexConsumer(val isValid: (Char, Int) -> Boolean) : TokenTypeProperty
|
||||||
open class TokenUpgrader(val maybeUpgrade: (Token) -> Token?) : TokenTypeProperty
|
open class TokenUpgrader(val maybeUpgrade: (Token) -> Token?) : TokenTypeProperty
|
||||||
|
|
||||||
object KeywordUpgrader : TokenUpgrader({ token ->
|
object KeywordUpgrader : TokenUpgrader({ token ->
|
||||||
var upgraded: Token? = null
|
var upgraded: Token? = null
|
||||||
for (item in TokenType.Keywords) {
|
for (item in TokenType.ManyChars) {
|
||||||
if (item.keyword != null && token.text == item.keyword.text) {
|
if (item.manyChars != null && token.text == item.manyChars.text) {
|
||||||
upgraded = Token(item, token.start, token.text)
|
upgraded = Token(item, token.start, token.text)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -79,13 +79,18 @@ class Tokenizer(val source: CharSource) {
|
|||||||
|
|
||||||
var type = item
|
var type = item
|
||||||
var text = itemChar.toString()
|
var text = itemChar.toString()
|
||||||
for (promotion in item.promotions) {
|
var promoted = true
|
||||||
if (source.peek() != promotion.nextChar) {
|
while (promoted) {
|
||||||
continue
|
promoted = false
|
||||||
|
for (promotion in type.promotions) {
|
||||||
|
if (source.peek() != promotion.nextChar) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val nextChar = source.next()
|
||||||
|
type = promotion.type
|
||||||
|
text += nextChar
|
||||||
|
promoted = true
|
||||||
}
|
}
|
||||||
val nextChar = source.next()
|
|
||||||
type = promotion.type
|
|
||||||
text += nextChar
|
|
||||||
}
|
}
|
||||||
return Token(type, tokenStart, text)
|
return Token(type, tokenStart, text)
|
||||||
}
|
}
|
||||||
|
2
stdlib/src/main/pork/lang/prelude.pork
Normal file
2
stdlib/src/main/pork/lang/prelude.pork
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export func println(messages...)
|
||||||
|
native internal "println"
|
@ -1,2 +1,3 @@
|
|||||||
|
lang/prelude.pork
|
||||||
ffi/malloc.pork
|
ffi/malloc.pork
|
||||||
numerics/operator.pork
|
numerics/operator.pork
|
||||||
|
@ -19,21 +19,10 @@ class RunCommand : CliktCommand(help = "Run Program", name = "run") {
|
|||||||
override fun run() {
|
override fun run() {
|
||||||
val tool = FileTool(PlatformFsProvider.resolve(path))
|
val tool = FileTool(PlatformFsProvider.resolve(path))
|
||||||
val scope = Scope()
|
val scope = Scope()
|
||||||
scope.define("println", CallableFunction { arguments ->
|
|
||||||
if (quiet) {
|
|
||||||
return@CallableFunction None
|
|
||||||
}
|
|
||||||
when (arguments.values.count()) {
|
|
||||||
0 -> println()
|
|
||||||
1 -> println(arguments.values[0])
|
|
||||||
else -> println(arguments.values.joinToString(" "))
|
|
||||||
}
|
|
||||||
None
|
|
||||||
})
|
|
||||||
|
|
||||||
val main = tool.loadMainFunction(scope, setupEvaluator = {
|
val main = tool.loadMainFunction(scope, setupEvaluator = {
|
||||||
addNativeFunctionProvider("ffi", JnaNativeProvider())
|
addNativeProvider("internal", InternalNativeProvider(quiet = quiet))
|
||||||
addNativeFunctionProvider("java", JavaNativeProvider())
|
addNativeProvider("ffi", JnaNativeProvider())
|
||||||
|
addNativeProvider("java", JavaNativeProvider())
|
||||||
})
|
})
|
||||||
|
|
||||||
if (dumpScope) {
|
if (dumpScope) {
|
||||||
|
@ -5,6 +5,7 @@ import gay.pizza.pork.ast.NodeVisitor
|
|||||||
import gay.pizza.pork.ast.visit
|
import gay.pizza.pork.ast.visit
|
||||||
import gay.pizza.pork.evaluator.CallableFunction
|
import gay.pizza.pork.evaluator.CallableFunction
|
||||||
import gay.pizza.pork.evaluator.Evaluator
|
import gay.pizza.pork.evaluator.Evaluator
|
||||||
|
import gay.pizza.pork.evaluator.InternalNativeProvider
|
||||||
import gay.pizza.pork.evaluator.Scope
|
import gay.pizza.pork.evaluator.Scope
|
||||||
import gay.pizza.pork.ffi.JavaAutogenContentSource
|
import gay.pizza.pork.ffi.JavaAutogenContentSource
|
||||||
import gay.pizza.pork.frontend.ContentSource
|
import gay.pizza.pork.frontend.ContentSource
|
||||||
|
Loading…
Reference in New Issue
Block a user