| -------------------------------------------------------------------------------- |
| -- Copyright (c) 2011-2012 Sierra Wireless. |
| -- All rights reserved. This program and the accompanying materials |
| -- are made available under the terms of the Eclipse Public License v1.0 |
| -- which accompanies this distribution, and is available at |
| -- http://www.eclipse.org/legal/epl-v10.html |
| -- |
| -- Contributors: |
| -- Simon BERNARD <sbernard@sierrawireless.com> |
| -- - initial API and implementation and initial documentation |
| -------------------------------------------------------------------------------- |
| local M = {} |
| |
| -------------------------------------------------------------------------------- |
| -- API MODEL |
| -------------------------------------------------------------------------------- |
| |
| function M._file() |
| local file = { |
| -- FIELDS |
| tag = "file", |
| name = nil, -- string |
| shortdescription = "", -- string |
| description = "", -- string |
| types = {}, -- map from typename to type |
| globalvars = {}, -- map from varname to item |
| returns = {}, -- list of return |
| |
| -- FUNCTIONS |
| addtype = function (self,type) |
| self.types[type.name] = type |
| type.parent = self |
| end, |
| |
| mergetype = function (self,newtype,erase,erasesourcerangefield) |
| local currenttype = self.types[newtype.name] |
| if currenttype then |
| -- merge recordtypedef |
| if currenttype.tag =="recordtypedef" and newtype.tag == "recordtypedef" then |
| -- merge fields |
| for fieldname ,field in pairs( newtype.fields) do |
| local currentfield = currenttype.fields[fieldname] |
| if erase or not currentfield then |
| currenttype:addfield(field) |
| elseif erasesourcerangefield then |
| if field.sourcerange.min and field.sourcerange.max then |
| currentfield.sourcerange.min = field.sourcerange.min |
| currentfield.sourcerange.max = field.sourcerange.max |
| end |
| end |
| end |
| |
| -- merge descriptions and source ranges |
| if erase then |
| if newtype.description or newtype.description == "" then currenttype.description = newtype.description end |
| if newtype.shortdescription or newtype.shortdescription == "" then currenttype.shortdescription = newtype.shortdescription end |
| if newtype.sourcerange.min and newtype.sourcerange.max then |
| currenttype.sourcerange.min = newtype.sourcerange.min |
| currenttype.sourcerange.max = newtype.sourcerange.max |
| end |
| end |
| -- merge functiontypedef |
| elseif currenttype.tag == "functiontypedef" and newtype.tag == "functiontypedef" then |
| -- merge params |
| for i, param1 in ipairs(newtype.params) do |
| local missing = true |
| for j, param2 in ipairs(currenttype.params) do |
| if param1.name == param2.name then |
| missing = false |
| break |
| end |
| end |
| if missing then |
| table.insert(currenttype.params,param1) |
| end |
| end |
| |
| -- merge descriptions and source ranges |
| if erase then |
| if newtype.description or newtype.description == "" then currenttype.description = newtype.description end |
| if newtype.shortdescription or newtype.shortdescription == "" then currenttype.shortdescription = newtype.shortdescription end |
| if newtype.sourcerange.min and newtype.sourcerange.max then |
| currenttype.sourcerange.min = newtype.sourcerange.min |
| currenttype.sourcerange.max = newtype.sourcerange.max |
| end |
| end |
| end |
| else |
| self:addtype(newtype) |
| end |
| end, |
| |
| addglobalvar = function (self,item) |
| self.globalvars[item.name] = item |
| item.parent = self |
| end, |
| |
| moduletyperef = function (self) |
| if self and self.returns[1] and self.returns[1].types[1] then |
| local typeref = self.returns[1].types[1] |
| return typeref |
| end |
| end |
| } |
| return file |
| end |
| |
| function M._recordtypedef(name) |
| local recordtype = { |
| -- FIELDS |
| tag = "recordtypedef", |
| name = name, -- string (mandatory) |
| shortdescription = "", -- string |
| description = "", -- string |
| fields = {}, -- map from fieldname to field |
| sourcerange = {min=0,max=0}, |
| supertype = nil, -- supertype of the type def (inheritance), should be a recordtypedef ref |
| defaultkeytyperef = nil, -- the default typeref of key |
| defaultvaluetyperef = nil, -- the default typeref of value |
| structurekind = nil, -- kind of structure of the type: could be nil, "map" or "list" |
| structuredescription = nil, -- description of the structure |
| call = nil, -- typeref to the function use as __call on the type. |
| -- FUNCTIONS |
| addfield = function (self,field) |
| self.fields[field.name] = field |
| field.parent = self |
| end, |
| |
| getcalldef = function( self) |
| if self.call and self.call.tag == 'internaltyperef' then |
| if self.parent and self.parent.tag == 'file' then |
| local file = self.parent |
| return file.types[self.call.typename] |
| end |
| end |
| end |
| } |
| return recordtype |
| end |
| |
| function M._functiontypedef(name) |
| return { |
| tag = "functiontypedef", |
| name = name, -- string (mandatory) |
| shortdescription = "", -- string |
| description = "", -- string |
| params = {}, -- list of parameter |
| returns = {} -- list of return |
| } |
| end |
| |
| function M._parameter(name) |
| return { |
| tag = "parameter", |
| name = name, -- string (mandatory) |
| description = "", -- string |
| type = nil -- typeref (external or internal or primitive typeref) |
| } |
| end |
| |
| function M._item(name) |
| return { |
| -- FIELDS |
| tag = "item", |
| name = name, -- string (mandatory) |
| shortdescription = "", -- string |
| description = "", -- string |
| type = nil, -- typeref (external or internal or primitive typeref) |
| occurrences = {}, -- list of identifier (see internalmodel) |
| sourcerange = {min=0, max=0}, |
| |
| -- This is A TRICK |
| -- This value is ALWAYS nil, except for internal purposes (short references). |
| external = nil, |
| |
| -- FUNCTIONS |
| addoccurence = function (self,occ) |
| table.insert(self.occurrences,occ) |
| occ.definition = self |
| end, |
| |
| resolvetype = function (self,file) |
| if self and self.type then |
| if self.type.tag =="internaltyperef" then |
| -- if file is not given try to retrieve it. |
| if not file then |
| if self.parent and self.parent.tag == 'recordtypedef' then |
| file = self.parent.parent |
| elseif self.parent.tag == 'file' then |
| file = self.parent |
| end |
| end |
| if file then return file.types[self.type.typename] end |
| elseif self.type.tag =="inlinetyperef" then |
| return self.type.def |
| end |
| end |
| end |
| } |
| end |
| |
| function M._externaltypref(modulename, typename) |
| return { |
| tag = "externaltyperef", |
| modulename = modulename, -- string |
| typename = typename -- string |
| } |
| end |
| |
| function M._internaltyperef(typename) |
| return { |
| tag = "internaltyperef", |
| typename = typename -- string |
| } |
| end |
| |
| function M._primitivetyperef(typename) |
| return { |
| tag = "primitivetyperef", |
| typename = typename -- string |
| } |
| end |
| |
| function M._moduletyperef(modulename,returnposition) |
| return { |
| tag = "moduletyperef", |
| modulename = modulename, -- string |
| returnposition = returnposition -- number |
| } |
| end |
| |
| function M._exprtyperef(expression,returnposition) |
| return { |
| tag = "exprtyperef", |
| expression = expression, -- expression (see internal model) |
| returnposition = returnposition -- number |
| } |
| end |
| |
| function M._inlinetyperef(definition) |
| return { |
| tag = "inlinetyperef", |
| def = definition, -- expression (see internal model) |
| |
| } |
| end |
| |
| function M._return(description) |
| return { |
| tag = "return", |
| description = description or "", -- string |
| types = {} -- list of typref (external or internal or primitive typeref) |
| } |
| end |
| return M |