Skip to content

Commit

Permalink
Move traits typeid to Nelua library to avoid caching codenames
Browse files Browse the repository at this point in the history
  • Loading branch information
edubart committed Dec 10, 2024
1 parent 841e6e9 commit b334929
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 28 deletions.
20 changes: 18 additions & 2 deletions lib/traits.nelua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@
The traits library provides utilities to gather type information.
]]

##[[
-- Counter that increment on every new defined type that are fundamentally different.
local typeid_counter = 0
-- Table of type's id by its codename.
local typeid_by_codename = {}
local function get_typeidof(vtype)
local id = typeid_by_codename[vtype.codename]
if not id then -- generate an id
id = typeid_counter
typeid_counter = typeid_counter + 1
typeid_by_codename[vtype.codename] = id
end
return id
end
]]
-- Namespace for traits module.
global traits: type = @record{}

Expand All @@ -22,7 +38,7 @@ The given `v` can be either a runtime value or a compile-time type.
]]
function traits.typeidof(v: auto): traits.typeid <inline>
## local vtype = v.type.is_type and v.value or v.type
return #[vtype.id]#
return #[get_typeidof(vtype)]#
end

--[[
Expand All @@ -32,7 +48,7 @@ The given `v` can be either a runtime value or a compile-time type.
function traits.typeinfoof(v: auto): traits.typeinfo <inline>
## local vtype = v.type.is_type and v.value or v.type
return (@traits.typeinfo){
id = #[vtype.id]#,
id = #[get_typeidof(vtype)]#,
name = #[vtype.name]#,
nickname = #[vtype.nickname or '']#,
codename = #[vtype.codename]#
Expand Down
8 changes: 6 additions & 2 deletions lualib/nelua/analyzer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ local iters = require 'nelua.utils.iterators'
local traits = require 'nelua.utils.traits'
local tabler = require 'nelua.utils.tabler'
local pegger = require 'nelua.utils.pegger'
local defer = require 'nelua.utils.defer'
local fs = require 'nelua.utils.fs'
local typedefs = require 'nelua.typedefs'
local Attr = require 'nelua.attr'
Expand Down Expand Up @@ -3394,6 +3395,11 @@ function analyzer.analyze(context)
-- save current analyzing context
local old_current_context = analyzer.current_context
analyzer.current_context = context
local _ <close> = defer(function()
-- restore old analyzing context
analyzer.current_context = old_current_context
end)

-- begin tracking analyze time
local timer
if config.more_timing then
Expand Down Expand Up @@ -3449,8 +3455,6 @@ function analyzer.analyze(context)
callback()
end
context:pop_state()
-- restore old analyzing context
analyzer.current_context = old_current_context
return context
end

Expand Down
26 changes: 2 additions & 24 deletions lualib/nelua/types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ local ASTNode = require 'nelua.astnode'

local types = {}

-- Counter that increment on every new defined type that are fundamentally different.
local typeid_counter = 0

-- Table of type's id by its codename.
local typeid_by_codename = {}

-- These are set by types.set_typedefs when typedefs file is loaded.
local typedefs, primtypes

Expand All @@ -42,8 +36,6 @@ types.Type = Type
-- Define the shape of all fields used in the type.
-- Use this as a reference to know all used fields in the Type class by the compiler.
Type.shape = shaper.shape {
-- Unique identifier for the type, used when needed for runtime type information.
id = shaper.integer,
-- Size of the type at runtime in bytes.
size = shaper.integer:is_optional(),
-- Size of the type at runtime in bits.
Expand Down Expand Up @@ -251,15 +243,6 @@ function Type:_init(name, size)
self.codename = 'nl' .. self.name
end

-- generate an unique id for this type in case not generated yet for this codename
local id = typeid_by_codename[self.codename]
if not id then -- generate an id
id = typeid_counter
typeid_counter = typeid_counter + 1
typeid_by_codename[self.codename] = id
end
self.id = id

-- set unary and binary operators tables
local mt = getmetatable(self)
self.unary_operators = setmetatable({}, {__index = mt.unary_operators})
Expand All @@ -269,7 +252,6 @@ end
-- Set a new codename for this type, storing it in the typeid table.
function Type:set_codename(codename)
self.codename = codename
typeid_by_codename[codename] = self.id
end

-- Set a nickname for this type if not set yet.
Expand Down Expand Up @@ -400,7 +382,7 @@ end
-- Checks if this type equals to another type.
-- Usually this is overwritten by derived types, but this is a fallback implementation.
function Type:is_equal(type)
return type.id == self.id
return type.codename == self.codename
end

-- Give the underlying type when implicit dereferencing this type.
Expand Down Expand Up @@ -441,10 +423,6 @@ end
-- Compare if two types are equal.
function Type.__eq(t1, t2)
if getmetatable(t1) == getmetatable(t2) then
if t1.id == t2.id then -- early check for same type (optimization)
-- types with the same type id should always be the same
return true
end
return t1:is_equal(t2)
end
return false
Expand Down Expand Up @@ -1106,7 +1084,7 @@ end
-- Get the desired type when converting this type from another type.
function IntegralType:get_convertible_from_type(type, explicit, fromcall)
if type.is_integral then
if type.id == self.id then
if type.codename == self.codename then
-- early return for the same type
return self
elseif self:is_type_inrange(type) then
Expand Down
10 changes: 10 additions & 0 deletions lualib/nelua/utils/defer.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--[[
Defer module
]]
-- Execute function at end of the scope, even when an error is raised.
local function defer(f)
return setmetatable({}, {__close = f})
end

return defer

0 comments on commit b334929

Please sign in to comment.