Skip to content

Commit

Permalink
Improve E2 Constants (#2846)
Browse files Browse the repository at this point in the history
* Better constants

* Update vector.lua
  • Loading branch information
Vurv78 authored Nov 15, 2023
1 parent 3f56545 commit 84f1f54
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 26 deletions.
65 changes: 65 additions & 0 deletions lua/entities/gmod_wire_expression2/base/compiler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
AddCSLuaFile()

local Warning, Error = E2Lib.Debug.Warning, E2Lib.Debug.Error
local Token, TokenVariant = E2Lib.Tokenizer.Token, E2Lib.Tokenizer.Variant
local Node, NodeVariant = E2Lib.Parser.Node, E2Lib.Parser.Variant
local Operator = E2Lib.Operator

Expand Down Expand Up @@ -1211,6 +1212,70 @@ local CompileVisitors = {
end, var.type
end,

---@param data Token<string>
[NodeVariant.ExprConstant] = function (self, trace, data, used_as_stmt)
local value = self:Assert( wire_expression2_constants[data.value], "Invalid constant: " .. data.value, trace ).value

local ty = type(value)
if ty == "number" then
return self:CompileExpr( Node.new(NodeVariant.ExprLiteral, { "n", value }, trace) )
elseif ty == "string" then
return self:CompileExpr( Node.new(NodeVariant.ExprLiteral, { "s", value }, trace) )
elseif ty == "Vector" and wire_expression2_funcs["vec(nnn)"] then
return self:CompileExpr(Node.new(NodeVariant.ExprCall, {
Token.new(TokenVariant.String, "vec"),
{
Node.new(NodeVariant.ExprLiteral, { "n", value[1] }, trace),
Node.new(NodeVariant.ExprLiteral, { "n", value[2] }, trace),
Node.new(NodeVariant.ExprLiteral, { "n", value[3] }, trace)
}
}, trace))
elseif ty == "Angle" and wire_expression2_funcs["ang(nnn)"] then
return self:CompileExpr(Node.new(NodeVariant.ExprCall, {
Token.new(TokenVariant.String, "ang"),
{
Node.new(NodeVariant.ExprLiteral, { "n", value[1] }, trace),
Node.new(NodeVariant.ExprLiteral, { "n", value[2] }, trace),
Node.new(NodeVariant.ExprLiteral, { "n", value[3] }, trace)
}
}, trace))
elseif ty == "table" then -- Know it's an array already from registerConstant
local out = {}
for i, val in ipairs(value) do
local ty = type(val)
if ty == "number" then
out[i] = Node.new(NodeVariant.ExprLiteral, { "n", val }, trace)
elseif ty == "string" then
out[i] = Node.new(NodeVariant.ExprLiteral, { "s", val }, trace)
elseif ty == "Vector" then
out[i] = Node.new(NodeVariant.ExprCall, {
Token.new(TokenVariant.String, "vec"),
{
Node.new(NodeVariant.ExprLiteral, { "n", val[1] }, trace),
Node.new(NodeVariant.ExprLiteral, { "n", val[2] }, trace),
Node.new(NodeVariant.ExprLiteral, { "n", val[3] }, trace)
}
}, trace)
elseif ty == "Angle" then
out[i] = Node.new(NodeVariant.ExprCall, {
Token.new(TokenVariant.String, "ang"),
{
Node.new(NodeVariant.ExprLiteral, { "n", val[1] }, trace),
Node.new(NodeVariant.ExprLiteral, { "n", val[2] }, trace),
Node.new(NodeVariant.ExprLiteral, { "n", val[3] }, trace)
}
}, trace)
else
self:Error("Constant " .. data.value .. " has invalid data type", trace)
end
end

return self:CompileExpr( Node.new(NodeVariant.ExprArray, out, trace) )
else
self:Error("Constant " .. data.value .. " has invalid data type", trace)
end
end,

---@param data Node[]|{ [1]: Node, [2]:Node }[]
[NodeVariant.ExprArray] = function (self, trace, data)
if #data == 0 then
Expand Down
8 changes: 7 additions & 1 deletion lua/entities/gmod_wire_expression2/base/parser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ local NodeVariant = {
ExprTable = 35, -- `table(1, 2, 3)` or `table(1 = 2, "test" = 3)`
ExprFunction = 36, -- `function() {}`
ExprLiteral = 37, -- `"test"` `5e2` `4.023` `4j`
ExprIdent = 38 -- `Variable`
ExprIdent = 38, -- `Variable`
ExprConstant = 39, -- `_FOO`
}

Parser.Variant = NodeVariant
Expand Down Expand Up @@ -1002,6 +1003,11 @@ function Parser:Expr15()
return Node.new(NodeVariant.ExprIdent, ident, ident.trace)
end

local constant = self:Consume(TokenVariant.Constant)
if constant then
return Node.new(NodeVariant.ExprConstant, constant, constant.trace)
end

-- Error Messages
if self:Eof() then
self:Error("Further input required at end of code, incomplete expression")
Expand Down
11 changes: 1 addition & 10 deletions lua/entities/gmod_wire_expression2/base/tokenizer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -276,16 +276,7 @@ function Tokenizer:Next()

match = self:ConsumePattern("^_[A-Z0-9_]+")
if match then
-- Constant value
local value = wire_expression2_constants[match]

if type(value) == "number" then
return Token.new(TokenVariant.Decimal, value)
elseif type(value) == "string" then
return Token.new(TokenVariant.String, value)
else
return self:Error("Constant (" .. match .. ") has invalid data type (" .. type(value) .. ")")
end
return Token.new(TokenVariant.Constant, match)
end

if self:ConsumePattern("^_") then
Expand Down
39 changes: 36 additions & 3 deletions lua/entities/gmod_wire_expression2/core/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,46 @@ function registerFunction(name, pars, rets, func, cost, argnames, attributes)
wire_expression2_funclist[name] = true
end

function E2Lib.registerConstant(name, value)
---@alias E2Constant string | number | E2Constant[]

local TypeMap = {
["number"] = "n", ["string"] = "s",
["Vector"] = "v", ["Angle"] = "a",
["table"] = "r"
}

local ValidArrayTypes = {
["number"] = true, ["string"] = true,
["Vector"] = true, ["Angle"] = true
}

---@param value E2Constant
---@param description string?
function E2Lib.registerConstant(name, value, description)
if name:sub(1, 1) ~= "_" then name = "_" .. name end

local ty = type(value)
assert(ty == "number" or ty == "string", "Invalid value passed to registerConstant (must be number or string)")
local e2ty = TypeMap[ty]

if e2ty then
if ty == "table" then -- ensure it's actually an array (sequential and valid types)
local i = 1
for _, val in pairs(value) do
assert(value[i] ~= nil, "Invalid array passed to registerConstant (must be sequential)")
assert(ValidArrayTypes[type(val)], "Invalid array passed to registerConstant (must only contain numbers, strings, vector or angles)")
i = i + 1
end
end

wire_expression2_constants[name] = value
wire_expression2_constants[name] = {
value = value,
type = e2ty,
description = description,
extension = E2Lib.currentextension
}
else
error("Invalid value passed to registerConstant. Only numbers, strings, vectors, angles and arrays can be constant values.")
end
end

--- Example:
Expand Down
3 changes: 3 additions & 0 deletions lua/entities/gmod_wire_expression2/core/vector.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ registerType("vector", "v", Vector(0, 0, 0),
end
)

E2Lib.registerConstant("VECTOR_ORIGIN", Vector(0, 0, 0), "Origin of the map. This is vec(0, 0, 0)")
E2Lib.registerConstant("VECTOR_UP", Vector(0, 0, 1), "Upward direction. This is vec(0, 0, 1)")

--------------------------------------------------------------------------------

__e2setcost(1) -- approximated
Expand Down
23 changes: 13 additions & 10 deletions lua/wire/client/e2helper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,17 @@ function E2Helper.Create(reset)
self:ClearSelection()
self:SelectItem(line)

-- don't try describing the function when it is actually a constant
if E2Helper.constants[line] then
E2Helper.FuncEntry:SetText("Constant value")
local const = E2Helper.constants[line]
if const then
E2Helper.FuncEntry:SetText(line:GetValue(1) .. " (" .. const.type .. ")")

E2Helper.DescriptionEntry:SetText("Constants do not support descriptions (yet)")
E2Helper.DescriptionEntry:SetTextColor(Color(128, 128, 128))
if const.description then
E2Helper.DescriptionEntry:SetText(const.description)
E2Helper.DescriptionEntry:SetTextColor(Color(0, 0, 0))
else
E2Helper.DescriptionEntry:SetText("No description found :(")
E2Helper.DescriptionEntry:SetTextColor(Color(128, 128, 128))
end
else
E2Helper.FuncEntry:SetText(E2Helper.GetFunctionSyntax(line:GetValue(1), line:GetValue(3), line:GetValue(4)))
local desc = getdesc(line:GetValue(1), line:GetValue(3))
Expand Down Expand Up @@ -314,13 +319,11 @@ function E2Helper.Update()
E2Helper.constants = {}
if E2Helper.CurrentMode == true then
for k, v in pairs(wire_expression2_constants) do
local strType = isstring(v) and "s" or "n"

-- constants have no arguments and no cost
local name, args, rets, cost = k, nil, strType, 0
local name, args, rets, cost = k, nil, v.type, 0
if name:lower():find(search_name, 1, true) and search_args == "" and rets:lower():find(search_rets, 1, true) and string.find("constants",search_from, 1, true) then
local line = E2Helper.ResultFrame:AddLine(name, "constants", args, rets, cost)
E2Helper.constants[line] = true
local line = E2Helper.ResultFrame:AddLine(name, v.extension, args, rets, cost)
E2Helper.constants[line] = v
count = count + 1
if count >= maxcount then break end
end
Expand Down
2 changes: 1 addition & 1 deletion lua/wire/client/text_editor/modes/e2.lua
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ function EDITOR:SyntaxColorLine(row)
-- eat next token
if self:NextPattern("^_[A-Z][A-Z_0-9]*") then
local word = self.tokendata
for k,_ in pairs( wire_expression2_constants ) do
for k in pairs( wire_expression2_constants ) do
if k == word then
tokenname = "constant"
end
Expand Down
2 changes: 1 addition & 1 deletion lua/wire/client/text_editor/texteditor.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2129,7 +2129,7 @@ local function FindConstants( self, word )

local suggestions = {}

for name, _ in pairs( wire_expression2_constants ) do
for name in pairs( wire_expression2_constants ) do
if name:sub(1,len) == wordu then
count = count + 1
suggestions[count] = GetTableForConstant( name )
Expand Down

0 comments on commit 84f1f54

Please sign in to comment.