mirror of
https://github.com/wiremod/wire.git
synced 2025-03-04 03:03:04 -05:00
Add constant variables to E2 (#2769)
This commit is contained in:
parent
09e9e3dcbb
commit
d7c73b08dd
@ -0,0 +1,5 @@
|
||||
## SHOULD_FAIL:COMPILE
|
||||
|
||||
const X = 5
|
||||
|
||||
X = 2
|
@ -0,0 +1,4 @@
|
||||
## SHOULD_FAIL:COMPILE
|
||||
|
||||
const Y = 2
|
||||
const Y = 1
|
@ -0,0 +1,4 @@
|
||||
## SHOULD_FAIL:COMPILE
|
||||
|
||||
const X = 5
|
||||
local X = 2
|
@ -0,0 +1,4 @@
|
||||
## SHOULD_FAIL:COMPILE
|
||||
|
||||
const Z = "Foo"
|
||||
A=Z="Y"
|
4
data/expression2/tests/compiler/parser/const.txt
Normal file
4
data/expression2/tests/compiler/parser/const.txt
Normal file
@ -0,0 +1,4 @@
|
||||
## SHOULD_PASS:COMPILE
|
||||
|
||||
const Var = 5
|
||||
const Xyz = "test"
|
@ -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
|
||||
|
@ -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.")
|
||||
|
@ -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
|
||||
|
@ -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 },
|
||||
|
Loading…
Reference in New Issue
Block a user