Add constant variables to E2 (#2769)

This commit is contained in:
Vurv 2023-10-04 09:11:43 -07:00 committed by GitHub
parent 09e9e3dcbb
commit d7c73b08dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 89 additions and 40 deletions

View File

@ -0,0 +1,5 @@
## SHOULD_FAIL:COMPILE
const X = 5
X = 2

View File

@ -0,0 +1,4 @@
## SHOULD_FAIL:COMPILE
const Y = 2
const Y = 1

View File

@ -0,0 +1,4 @@
## SHOULD_FAIL:COMPILE
const X = 5
local X = 2

View File

@ -0,0 +1,4 @@
## SHOULD_FAIL:COMPILE
const Z = "Foo"
A=Z="Y"

View File

@ -0,0 +1,4 @@
## SHOULD_PASS:COMPILE
const Var = 5
const Xyz = "test"

View File

@ -23,7 +23,7 @@ end, "compiler_quota_check")
---@field function { [1]: string, [2]: EnvFunction}?
---@field ops integer
---@alias VarData { type: string, trace_if_unused: Trace?, initialized: boolean, depth: integer }
---@alias VarData { type: string, trace_if_unused: Trace?, const: boolean, initialized: boolean, depth: integer }
---@class Scope
---@field parent Scope?
@ -917,6 +917,8 @@ local CompileVisitors = {
-- Local declaration. Fastest case.
local var_name = data[2][1][1].value
self:AssertW(not self.scope.vars[var_name], "Do not redeclare existing variable " .. var_name, trace)
self:Assert(not self.scope.vars[var_name] or not self.scope.vars[var_name].const, "Cannot redeclare constant variable", trace)
self.scope:DeclVar(var_name, { initialized = true, trace_if_unused = data[2][1][1].trace, type = value_ty })
return function(state) ---@param state RuntimeContext
state.Scope[var_name] = value(state)
@ -973,6 +975,7 @@ local CompileVisitors = {
end
else
self:Assert(existing.type == value_ty, "Cannot assign type (" .. value_ty .. ") to variable of type (" .. existing.type .. ")", trace)
self:Assert(not existing.const, "Cannot assign to constant variable " .. var, trace)
existing.initialized = true
local id = existing.depth
@ -1029,6 +1032,17 @@ local CompileVisitors = {
end
end,
---@param data { [1]: Token<string>, [2]: Node }
[NodeVariant.Const] = function (self, trace, data)
local name, expr, expr_ty = data[1].value, self:CompileExpr(data[2])
self:Assert(not self.scope.vars[name], "Cannot redeclare existing variable " .. name, trace)
self.scope:DeclVar(name, { type = expr_ty, initialized = true, const = true, trace_if_unused = data[1].trace })
return function(state)
state.Scope[name] = expr(state)
end
end,
---@param data Token<string>
[NodeVariant.Increment] = function (self, trace, data)
-- Transform V-- to V = V + 1

View File

@ -70,35 +70,36 @@ local NodeVariant = {
Decrement = 10, -- `--`
CompoundArithmetic = 11, -- `+=`, `-=`, `*=`, `/=`
Assignment = 12, -- `X = Y[2, number] = Z[2] = 5` or `local X = 5`
Const = 13, -- const X = 5
Switch = 13, -- `switch (<EXPR>) { case <EXPR>, <STMT>* default, <STMT*> }
Function = 14, -- `function test() {}`
Include = 15, -- #include "file"
Try = 16, -- try {} catch (Err) {}
Switch = 14, -- `switch (<EXPR>) { case <EXPR>, <STMT>* default, <STMT*> }
Function = 15, -- `function test() {}`
Include = 16, -- #include "file"
Try = 17, -- try {} catch (Err) {}
--- Compile time constructs
Event = 17, -- event tick() {}
Event = 18, -- event tick() {}
--- Expressions
ExprTernary = 18, -- `X ? Y : Z`
ExprDefault = 19, -- `X ?: Y`
ExprLogicalOp = 20, -- `|` `&` (Yes they are flipped.)
ExprBinaryOp = 21, -- `||` `&&` `^^`
ExprComparison = 22, -- `>` `<` `>=` `<=`
ExprEquals = 23, -- `==` `!=`
ExprBitShift = 24, -- `>>` `<<`
ExprArithmetic = 25, -- `+` `-` `*` `/` `^` `%`
ExprUnaryOp = 26, -- `-` `+` `!`
ExprMethodCall = 27, -- `<EXPR>:call()`
ExprIndex = 28, -- `<EXPR>[<EXPR>, <type>?]`
ExprGrouped = 29, -- (<EXPR>)
ExprCall = 30, -- `call()`
ExprStringCall = 31, -- `""()` (Temporary until lambdas are made)
ExprUnaryWire = 32, -- `~Var` `$Var` `->Var`
ExprArray = 33, -- `array(1, 2, 3)` or `array(1 = 2, 2 = 3)`
ExprTable = 34, -- `table(1, 2, 3)` or `table(1 = 2, "test" = 3)`
ExprLiteral = 35, -- `"test"` `5e2` `4.023` `4j`
ExprIdent = 36 -- `Variable`
ExprTernary = 19, -- `X ? Y : Z`
ExprDefault = 20, -- `X ?: Y`
ExprLogicalOp = 21, -- `|` `&` (Yes they are flipped.)
ExprBinaryOp = 22, -- `||` `&&` `^^`
ExprComparison = 23, -- `>` `<` `>=` `<=`
ExprEquals = 24, -- `==` `!=`
ExprBitShift = 25, -- `>>` `<<`
ExprArithmetic = 26, -- `+` `-` `*` `/` `^` `%`
ExprUnaryOp = 27, -- `-` `+` `!`
ExprMethodCall = 28, -- `<EXPR>:call()`
ExprIndex = 29, -- `<EXPR>[<EXPR>, <type>?]`
ExprGrouped = 30, -- (<EXPR>)
ExprCall = 31, -- `call()`
ExprStringCall = 32, -- `""()` (Temporary until lambdas are made)
ExprUnaryWire = 33, -- `~Var` `$Var` `->Var`
ExprArray = 34, -- `array(1, 2, 3)` or `array(1 = 2, 2 = 3)`
ExprTable = 35, -- `table(1, 2, 3)` or `table(1 = 2, "test" = 3)`
ExprLiteral = 36, -- `"test"` `5e2` `4.023` `4j`
ExprIdent = 37 -- `Variable`
}
Parser.Variant = NodeVariant
@ -348,6 +349,16 @@ function Parser:Stmt()
self.index = self.index - 1
end
if self:Consume(TokenVariant.Keyword, Keyword.Const) then
local trace = self:Prev().trace
local name = self:Assert(self:Consume(TokenVariant.Ident), "Expected variable name after const")
self:Assert( self:Consume(TokenVariant.Operator, Operator.Ass), "Expected = for constant declaration" )
local value = self:Assert(self:Expr(), "Expected expression for constant declaration")
return Node.new(NodeVariant.Const, { name, value }, trace:stitch(self:Prev().trace))
end
local is_local, var = self:Consume(TokenVariant.Keyword, Keyword.Local), self:Consume(TokenVariant.Ident)
if not var then
self:Assert(not is_local, "Invalid operator (local) must be used for variable declaration.")

View File

@ -420,36 +420,38 @@ local Keyword = {
Else = 3,
-- ``local``
Local = 4,
-- ``const``
Const = 5,
-- ``while``
While = 5,
While = 6,
-- ``for``
For = 6,
For = 7,
-- ``break``
Break = 7,
Break = 8,
-- ``continue``
Continue = 8,
Continue = 9,
-- ``switch``
Switch = 9,
Switch = 10,
-- ``case``
Case = 10,
Case = 11,
-- ``default``
Default = 11,
Default = 12,
-- ``foreach``
Foreach = 12,
Foreach = 13,
-- ``function``
Function = 13,
Function = 14,
-- ``return``
Return = 14,
Return = 15,
-- ``#include``
["#Include"] = 15,
["#Include"] = 16,
-- ``try``
Try = 16,
Try = 17,
-- ``catch``
Catch = 17,
Catch = 18,
-- ``do``
Do = 18,
Do = 19,
-- ``event``
Event = 19
Event = 20
}
E2Lib.Keyword = Keyword

View File

@ -29,6 +29,7 @@ local keywords = {
["function"] = { [true] = true },
["return"] = { [true] = true },
["local"] = { [true] = true },
["const"] = { [true] = true },
["try"] = { [true] = true },
["do"] = { [true] = true },
["event"] = { [true] = true },