diff --git a/nelua/analyzer.lua b/nelua/analyzer.lua index 5a9c5019..d107d473 100644 --- a/nelua/analyzer.lua +++ b/nelua/analyzer.lua @@ -440,6 +440,23 @@ function visitors.Annotation(context, node, symbol) end elseif name == 'codename' then objattr.fixedcodename = params + elseif name == 'using' then + assert(objattr._type) + if not objattr.is_enum then + node:raisef("annotation 'using' can only be used with enums") + end + -- inject all enum fields as comptime values + for _,field in ipairs(objattr.fields) do + local fieldsymbol = Symbol{ + name = field.name, + codename = objattr.codename..'_'..field.name, + comptime = true, + type = objattr, + value = field.value, + scope = symbol.scope, + } + symbol.scope:add_symbol(fieldsymbol) + end end node.done = true diff --git a/nelua/typedefs.lua b/nelua/typedefs.lua index 53d994b8..e228e8e9 100644 --- a/nelua/typedefs.lua +++ b/nelua/typedefs.lua @@ -265,6 +265,8 @@ typedefs.type_annots = { -- Mark a record type for forward declaration. -- This allows to use pointers to a record before defining it. forwarddecl = true, + -- Whether to use enum fields in the declared scope. + using = true, } return typedefs diff --git a/spec/03-typechecker_spec.lua b/spec/03-typechecker_spec.lua index b722ed92..5e3d606b 100644 --- a/spec/03-typechecker_spec.lua +++ b/spec/03-typechecker_spec.lua @@ -1754,4 +1754,17 @@ it("forward type declaration", function() "cannot be of forward declared type") end) +it("using annotation", function() + assert.analyze_ast([[ + local MyEnum = @enum{ + MYENUM_NONE = 0, + MYENUM_ONE = 1, + } + local a: MyEnum = MYENUM_ONE + ]]) + assert.analyze_error([[ + local MyEnum = @record{} + ]], "annotation 'using' can only") +end) + end)