Introduce the requirement of let for assignment.

This commit is contained in:
Alex Zenla 2023-09-04 02:33:13 -07:00
parent 128f40bcf4
commit 3545aa076f
Signed by: alex
GPG Key ID: C0780728420EBFE5
10 changed files with 40 additions and 28 deletions

View File

@ -4,15 +4,15 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName("assignment") @SerialName("letAssignment")
class Assignment(val symbol: Symbol, val value: Expression) : Expression() { class LetAssignment(val symbol: Symbol, val value: Expression) : Expression() {
override val type: NodeType = NodeType.Assignment override val type: NodeType = NodeType.LetAssignment
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> = override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
visitor.visitNodes(symbol, value) visitor.visitNodes(symbol, value)
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is Assignment) return false if (other !is LetAssignment) return false
return other.symbol == symbol && other.value == value return other.symbol == symbol && other.value == value
} }

View File

@ -7,7 +7,7 @@ class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor<Unit> {
override fun visitListLiteral(node: ListLiteral): Unit = handle(node) override fun visitListLiteral(node: ListLiteral): Unit = handle(node)
override fun visitSymbol(node: Symbol): Unit = handle(node) override fun visitSymbol(node: Symbol): Unit = handle(node)
override fun visitFunctionCall(node: FunctionCall): Unit = handle(node) override fun visitFunctionCall(node: FunctionCall): Unit = handle(node)
override fun visitDefine(node: Assignment): Unit = handle(node) override fun visitLetAssignment(node: LetAssignment): Unit = handle(node)
override fun visitSymbolReference(node: SymbolReference): Unit = handle(node) override fun visitSymbolReference(node: SymbolReference): Unit = handle(node)
override fun visitLambda(node: Lambda): Unit = handle(node) override fun visitLambda(node: Lambda): Unit = handle(node)
override fun visitParentheses(node: Parentheses): Unit = handle(node) override fun visitParentheses(node: Parentheses): Unit = handle(node)

View File

@ -12,7 +12,7 @@ enum class NodeType(val parent: NodeType? = null) {
ListLiteral(Expression), ListLiteral(Expression),
StringLiteral(Expression), StringLiteral(Expression),
Parentheses(Expression), Parentheses(Expression),
Assignment(Expression), LetAssignment(Expression),
Lambda(Expression), Lambda(Expression),
PrefixOperation(Expression), PrefixOperation(Expression),
InfixOperation(Expression), InfixOperation(Expression),

View File

@ -7,7 +7,7 @@ interface NodeVisitor<T> {
fun visitListLiteral(node: ListLiteral): T fun visitListLiteral(node: ListLiteral): T
fun visitSymbol(node: Symbol): T fun visitSymbol(node: Symbol): T
fun visitFunctionCall(node: FunctionCall): T fun visitFunctionCall(node: FunctionCall): T
fun visitDefine(node: Assignment): T fun visitLetAssignment(node: LetAssignment): T
fun visitSymbolReference(node: SymbolReference): T fun visitSymbolReference(node: SymbolReference): T
fun visitLambda(node: Lambda): T fun visitLambda(node: Lambda): T
fun visitParentheses(node: Parentheses): T fun visitParentheses(node: Parentheses): T
@ -26,7 +26,7 @@ interface NodeVisitor<T> {
is BooleanLiteral -> visitBooleanLiteral(node) is BooleanLiteral -> visitBooleanLiteral(node)
is ListLiteral -> visitListLiteral(node) is ListLiteral -> visitListLiteral(node)
is FunctionCall -> visitFunctionCall(node) is FunctionCall -> visitFunctionCall(node)
is Assignment -> visitDefine(node) is LetAssignment -> visitLetAssignment(node)
is SymbolReference -> visitSymbolReference(node) is SymbolReference -> visitSymbolReference(node)
is Lambda -> visitLambda(node) is Lambda -> visitLambda(node)
is Parentheses -> visitParentheses(node) is Parentheses -> visitParentheses(node)

View File

@ -17,7 +17,7 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
return currentScope.call(node.symbol.id, Arguments(arguments)) return currentScope.call(node.symbol.id, Arguments(arguments))
} }
override fun visitDefine(node: Assignment): Any { override fun visitLetAssignment(node: LetAssignment): Any {
val value = visit(node.value) val value = visit(node.value)
currentScope.define(node.symbol.id, value) currentScope.define(node.symbol.id, value)
return value return value

View File

@ -8,6 +8,6 @@ func fib(n) {
} }
export func main() { export func main() {
result = fib(20) let result = fib(20)
println(result) println(result)
} }

View File

@ -1,41 +1,41 @@
export func main() { export func main() {
three = 3 let three = 3
two = 2 let two = 2
calculateSimple = { in let calculateSimple = { in
(50 + three) * two (50 + three) * two
} }
calculateComplex = { in let calculateComplex = { in
three + two + 50 three + two + 50
} }
multiply = { a, b in let multiply = { a, b in
a * b a * b
} }
// calculates the result // calculates the result
calculateSimpleResult = calculateSimple() let calculateSimpleResult = calculateSimple()
calculateComplexResult = calculateComplex() let calculateComplexResult = calculateComplex()
multiplyResult = multiply(50, 50) let multiplyResult = multiply(50, 50)
list = [10, 20, 30] let list = [10, 20, 30]
trueValue = true let trueValue = true
falseValue = false let falseValue = false
invert = { value in let invert = { value in
!value !value
} }
notEqual = { a, b in let notEqual = { a, b in
a != b a != b
} }
equal = { a, b in let equal = { a, b in
a == b a == b
} }
results = [ let results = [
calculateSimpleResult, calculateSimpleResult,
calculateComplexResult, calculateComplexResult,
multiplyResult, multiplyResult,

View File

@ -31,6 +31,14 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
ListLiteral(items) ListLiteral(items)
} }
private fun readLetAssignment(): LetAssignment = within {
expect(TokenType.Let)
val symbol = readSymbolRaw()
expect(TokenType.Equals)
val value = readExpression()
LetAssignment(symbol, value)
}
private fun readSymbolRaw(): Symbol = within { private fun readSymbolRaw(): Symbol = within {
expect(TokenType.Symbol) { Symbol(it.text) } expect(TokenType.Symbol) { Symbol(it.text) }
} }
@ -43,8 +51,6 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
} }
expect(TokenType.RightParentheses) expect(TokenType.RightParentheses)
FunctionCall(symbol, arguments) FunctionCall(symbol, arguments)
} else if (next(TokenType.Equals)) {
Assignment(symbol, readExpression())
} else { } else {
SymbolReference(symbol) SymbolReference(symbol)
} }
@ -114,6 +120,10 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
readListLiteral() readListLiteral()
} }
TokenType.Let -> {
readLetAssignment()
}
TokenType.Symbol -> { TokenType.Symbol -> {
readSymbolCases() readSymbolCases()
} }

View File

@ -71,7 +71,8 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
append(")") append(")")
} }
override fun visitDefine(node: Assignment) { override fun visitLetAssignment(node: LetAssignment) {
append("let ")
visit(node.symbol) visit(node.symbol)
append(" = ") append(" = ")
visit(node.value) visit(node.value)

View File

@ -31,6 +31,7 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
Import(Keyword("import"), KeywordFamily), Import(Keyword("import"), KeywordFamily),
Export(Keyword("export"), KeywordFamily), Export(Keyword("export"), KeywordFamily),
Func(Keyword("func"), KeywordFamily), Func(Keyword("func"), KeywordFamily),
Let(Keyword("let"), 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),