Skip to content

Commit

Permalink
pragma: introduce --#pragma syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
hishamhm committed Jun 16, 2024
1 parent 3dc753c commit b429055
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 0 deletions.
29 changes: 29 additions & 0 deletions spec/pragma/invalid_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
local util = require("spec.util")

describe("invalid pragma", function()
it("rejects invalid pragma", util.check_syntax_error([[
--#invalid_pragma on
]], {
{ y = 1, msg = "invalid token '--#invalid_pragma'" }
}))

it("pragmas currently do not accept punctuation", util.check_syntax_error([[
--#pragma something(other)
]], {
{ y = 1, msg = "invalid token '('" },
{ y = 1, msg = "invalid token ')'" },
}))

it("pragma arguments need to be in a single line", util.check_syntax_error([[
--#pragma arity
on
local function f(x: integer, y: integer)
print(x + y)
end
print(f(10))
]], {
{ msg = "expected pragma value" }
}))
end)
73 changes: 73 additions & 0 deletions tl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,8 @@ end








Expand Down Expand Up @@ -830,6 +832,9 @@ do









Expand Down Expand Up @@ -866,6 +871,9 @@ do
["number hexfloat"] = "number",
["number power"] = "number",
["number powersign"] = "$ERR invalid_number$",
["pragma"] = "pragma",
["pragma any"] = nil,
["pragma word"] = "pragma_identifier",
}

local keywords = {
Expand Down Expand Up @@ -1010,6 +1018,10 @@ do
end
end

local valid_pragma = {
["--#pragma"] = true,
}

function tl.lex(input, filename)
local tokens = {}

Expand Down Expand Up @@ -1259,11 +1271,39 @@ do
elseif state == "got --" then
if c == "[" then
state = "got --["
elseif c == "#" then
state = "pragma"
else
fwd = false
state = "comment short"
drop_token()
end
elseif state == "pragma" then
if not lex_word[c] then
end_token_prev("pragma")
if not valid_pragma[tokens[nt].tk] then
add_syntax_error()
end
fwd = false
state = "pragma any"
end
elseif state == "pragma any" then
if c == "\n" then
state = "any"
elseif lex_word[c] then
state = "pragma word"
begin_token()
elseif not lex_space[c] then
begin_token()
end_token_here("$ERR invalid$")
add_syntax_error()
end
elseif state == "pragma word" then
if not lex_word[c] then
end_token_prev("pragma_identifier")
fwd = false
state = (c == "\n") and "any" or "pragma any"
end
elseif state == "got 0" then
if c == "x" or c == "X" then
state = "number hex"
Expand Down Expand Up @@ -1890,6 +1930,7 @@ end






local TruthyFact = {}
Expand Down Expand Up @@ -2070,6 +2111,10 @@ local Node = {ExpectedContext = {}, }










Expand Down Expand Up @@ -4123,7 +4168,27 @@ do
return parse_function(ps, i, "record")
end

local function parse_pragma(ps, i)
i = i + 1
local pragma = new_node(ps, i, "pragma")

if ps.tokens[i].kind ~= "pragma_identifier" then
return fail(ps, i, "expected pragma name")
end
pragma.pkey = ps.tokens[i].tk
i = i + 1

if ps.tokens[i].kind ~= "pragma_identifier" then
return fail(ps, i, "expected pragma value")
end
pragma.pvalue = ps.tokens[i].tk
i = i + 1

return i, pragma
end

local parse_statement_fns = {
["--#pragma"] = parse_pragma,
["::"] = parse_label,
["do"] = parse_do,
["if"] = parse_if,
Expand Down Expand Up @@ -4489,6 +4554,7 @@ local no_recurse_node = {
["break"] = true,
["label"] = true,
["number"] = true,
["pragma"] = true,
["string"] = true,
["boolean"] = true,
["integer"] = true,
Expand Down Expand Up @@ -5385,6 +5451,8 @@ function tl.pretty_print_ast(ast, gen_target, mode)
return out
end,
},
["pragma"] = {},

}

local visit_type = {}
Expand Down Expand Up @@ -11942,6 +12010,11 @@ self:expand_type(node, values, elements) })
return node.newtype
end,
},
["pragma"] = {
after = function(_self, _node, _children)
return NONE
end,
},
["error_node"] = {
after = function(_self, node, _children)
return a_type(node, "invalid", {})
Expand Down
73 changes: 73 additions & 0 deletions tl.tl
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,8 @@ local enum TokenKind
"identifier"
"number"
"integer"
"pragma"
"pragma_identifier"
"$ERR unfinished_comment$"
"$ERR invalid_string$"
"$ERR invalid_number$"
Expand Down Expand Up @@ -832,6 +834,9 @@ do
"number hexfloat"
"number power"
"number powersign"
"pragma"
"pragma word"
"pragma any"
end

local last_token_kind <total>: {LexState:TokenKind} = {
Expand Down Expand Up @@ -866,6 +871,9 @@ do
["number hexfloat"] = "number",
["number power"] = "number",
["number powersign"] = "$ERR invalid_number$",
["pragma"] = "pragma",
["pragma any"] = nil, -- never in a token
["pragma word"] = "pragma_identifier", -- never in a token
}

local keywords: {string:boolean} = {
Expand Down Expand Up @@ -1010,6 +1018,10 @@ do
end
end

local valid_pragma: {string:boolean} = {
["--#pragma"] = true
}

function tl.lex(input: string, filename: string): {Token}, {Error}
local tokens: {Token} = {}

Expand Down Expand Up @@ -1259,11 +1271,39 @@ do
elseif state == "got --" then
if c == "[" then
state = "got --["
elseif c == "#" then
state = "pragma"
else
fwd = false
state = "comment short"
drop_token()
end
elseif state == "pragma" then
if not lex_word[c] then
end_token_prev("pragma")
if not valid_pragma[tokens[nt].tk] then
add_syntax_error()
end
fwd = false
state = "pragma any"
end
elseif state == "pragma any" then
if c == "\n" then
state = "any"
elseif lex_word[c] then
state = "pragma word"
begin_token()
elseif not lex_space[c] then
begin_token()
end_token_here("$ERR invalid$")
add_syntax_error()
end
elseif state == "pragma word" then
if not lex_word[c] then
end_token_prev("pragma_identifier")
fwd = false
state = (c == "\n") and "any" or "pragma any"
end
elseif state == "got 0" then
if c == "x" or c == "X" then
state = "number hex"
Expand Down Expand Up @@ -1872,6 +1912,7 @@ local enum NodeKind
"macroexp"
"local_macroexp"
"interface"
"pragma"
"error_node"
end

Expand Down Expand Up @@ -2070,6 +2111,10 @@ local record Node
itemtype: Type
decltuple: TupleType

-- pragma
pkey: string
pvalue: string

opt: boolean

debug_type: Type
Expand Down Expand Up @@ -4123,7 +4168,27 @@ local function parse_record_function(ps: ParseState, i: integer): integer, Node
return parse_function(ps, i, "record")
end

local function parse_pragma(ps: ParseState, i: integer): integer, Node
i = i + 1 -- skip "--#pragma"
local pragma = new_node(ps, i, "pragma")

if ps.tokens[i].kind ~= "pragma_identifier" then
return fail(ps, i, "expected pragma name")
end
pragma.pkey = ps.tokens[i].tk
i = i + 1

if ps.tokens[i].kind ~= "pragma_identifier" then
return fail(ps, i, "expected pragma value")
end
pragma.pvalue = ps.tokens[i].tk
i = i + 1

return i, pragma
end

local parse_statement_fns: {string : function(ParseState, integer):(integer, Node)} = {
["--#pragma"] = parse_pragma,
["::"] = parse_label,
["do"] = parse_do,
["if"] = parse_if,
Expand Down Expand Up @@ -4489,6 +4554,7 @@ local no_recurse_node: {NodeKind : boolean} = {
["break"] = true,
["label"] = true,
["number"] = true,
["pragma"] = true,
["string"] = true,
["boolean"] = true,
["integer"] = true,
Expand Down Expand Up @@ -5385,6 +5451,8 @@ function tl.pretty_print_ast(ast: Node, gen_target: GenTarget, mode: boolean | P
return out
end,
},
["pragma"] = {
},
}

local visit_type: Visitor<nil, TypeName, Type, Output> = {}
Expand Down Expand Up @@ -11942,6 +12010,11 @@ do
return node.newtype
end,
},
["pragma"] = {
after = function(_self: TypeChecker, _node: Node, _children: {Type}): Type
return NONE
end,
},
["error_node"] = {
after = function(_self: TypeChecker, node: Node, _children: {Type}): Type
return an_invalid(node)
Expand Down

0 comments on commit b429055

Please sign in to comment.