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
@Serializable
@SerialName("assignment")
class Assignment(val symbol: Symbol, val value: Expression) : Expression() {
override val type: NodeType = NodeType.Assignment
@SerialName("letAssignment")
class LetAssignment(val symbol: Symbol, val value: Expression) : Expression() {
override val type: NodeType = NodeType.LetAssignment
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
visitor.visitNodes(symbol, value)
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
}

View File

@ -7,7 +7,7 @@ class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor<Unit> {
override fun visitListLiteral(node: ListLiteral): Unit = handle(node)
override fun visitSymbol(node: Symbol): 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 visitLambda(node: Lambda): 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),
StringLiteral(Expression),
Parentheses(Expression),
Assignment(Expression),
LetAssignment(Expression),
Lambda(Expression),
PrefixOperation(Expression),
InfixOperation(Expression),

View File

@ -7,7 +7,7 @@ interface NodeVisitor<T> {
fun visitListLiteral(node: ListLiteral): T
fun visitSymbol(node: Symbol): T
fun visitFunctionCall(node: FunctionCall): T
fun visitDefine(node: Assignment): T
fun visitLetAssignment(node: LetAssignment): T
fun visitSymbolReference(node: SymbolReference): T
fun visitLambda(node: Lambda): T
fun visitParentheses(node: Parentheses): T
@ -26,7 +26,7 @@ interface NodeVisitor<T> {
is BooleanLiteral -> visitBooleanLiteral(node)
is ListLiteral -> visitListLiteral(node)
is FunctionCall -> visitFunctionCall(node)
is Assignment -> visitDefine(node)
is LetAssignment -> visitLetAssignment(node)
is SymbolReference -> visitSymbolReference(node)
is Lambda -> visitLambda(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))
}
override fun visitDefine(node: Assignment): Any {
override fun visitLetAssignment(node: LetAssignment): Any {
val value = visit(node.value)
currentScope.define(node.symbol.id, value)
return value

View File

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

View File

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

View File

@ -31,6 +31,14 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
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 {
expect(TokenType.Symbol) { Symbol(it.text) }
}
@ -43,8 +51,6 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
}
expect(TokenType.RightParentheses)
FunctionCall(symbol, arguments)
} else if (next(TokenType.Equals)) {
Assignment(symbol, readExpression())
} else {
SymbolReference(symbol)
}
@ -114,6 +120,10 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
readListLiteral()
}
TokenType.Let -> {
readLetAssignment()
}
TokenType.Symbol -> {
readSymbolCases()
}

View File

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

View File

@ -31,6 +31,7 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
Import(Keyword("import"), KeywordFamily),
Export(Keyword("export"), KeywordFamily),
Func(Keyword("func"), KeywordFamily),
Let(Keyword("let"), KeywordFamily),
Whitespace(CharConsumer { it == ' ' || it == '\r' || it == '\n' || it == '\t' }),
BlockComment(CommentFamily),
LineComment(CommentFamily),