cmm_comp.py
# cmm_comp.py
from __future__ import print_function
import os, copy
import inspect
from cmm_parser import *
from cmm_product import *
from input import quoteString
from util import findColor
from code import *
# from cmm_code import *
from grammar import Grammar
from toparser import ToParser
from toproduct import ToProduct
# --------------------------------------------------------------------------
class NoQuote (object) :
def __init__ (self, value) :
self.value = value
def __repr__ (self) :
return self.value
# --------------------------------------------------------------------------
class CmmCompiler (Parser) :
def __init__ (self) :
super (CmmCompiler, self).__init__ ()
self.win = None
self.edit = None
self.global_scope = Namespace ()
self.global_scope.item_name = ""
self.global_scope.hidden_scope = True # do not print scope name
self.display = [ self.global_scope ]
self.top_decl_list = None
self.enable_declaration_stack = [ False ]
self.remember_compound_name = None
self.init_types ()
def compile_program (self) :
self.top_decl_list = CmmDeclSect ()
self.storeLocation (self.top_decl_list)
while self.token != self.eos :
self.top_decl_list.items.append (self.parse_declaration ())
# scope
def enter (self, item) :
inx = len (self.display) - 1
scope = self.display [inx]
while scope.search_only and inx > 0 :
inx = inx - 1
scope = self.display [inx]
if inx < 0 :
self.error ("All scopes are search-only")
self.enterIntoScope (scope, item)
item.item_place = self.display [-1] # last scope , even search_only
def enterIntoScope (self, scope, item) :
scope.item_dict [item.item_name] = item
scope.item_list.append (item)
item.item_place = scope
item.item_context = scope
if hasattr (scope, "item_qual") and scope.item_qual != None and scope.item_qual != "" :
item.item_qual = scope.item_qual + "." + item.item_name
else :
item.item_qual = item.item_name
# self.selectColor (item, defn = True)
def openScope (self, scope) :
self.display.append (scope)
def closeScope (self) :
self.display.pop ()
def searchScope (self, scope, name) :
return scope.item_dict.get (name, None)
def lookup (self, name) :
result = None
inx = len (self.display) - 1
while result == None and inx >= 0 :
result = self.display [inx].item_dict.get (name, None)
inx = inx - 1
return result
def openSearchOnlyScope (self, scope) :
look = copy.copy (scope)
look.search_only = True
self.openScope (look)
# special scopes
def register (self, scope, name, item) :
item.item_name = name
scope.registered_scopes [name] = item
item.item_context = scope
if hasattr (scope, "item_qual") and scope.item_qual != None and scope.item_qual != "" :
item.item_qual = scope.item_qual + "." + item.item_name
else :
item.item_qual = item.item_name
# namespace
def on_start_namespace (self, ns_decl) :
pass
def on_namespace (self, ns_decl) :
module = Namespace () # create Namespace object from code.py
module.link_code (ns_decl) # connect with parsed declaration (module.link_code <--> ns_decl.item_ref)
module.item_name = ns_decl.simp_name.id # store name
self.copy_name_location (module, ns_decl.simp_name) # store location
self.enter (module) # add identifier into scope
self.selectColor (module, table = "namespaceColors")
self.markDefn (module) # set attributes in text editor
self.markOutline (module)
self.custom_namespace (ns_decl)
def on_open_namespace (self, ns_decl) :
module = ns_decl.item_ref
self.openScope (module) # scope for identifiers
self.openCompletion (module) # area with text completion
def on_close_namespace (self, ns_decl) :
module = ns_decl.item_ref
self.closeCompletion (module)
self.closeScope ()
def on_stop_namespace (self, ns_decl) :
pass
# class
def on_start_class (self, cls_decl) :
cls = Class ()
cls.link_code (cls_decl)
# self.openRegion (cls) # region with background color
def on_class (self, cls_decl) :
cls = cls_decl.item_ref
cls.item_name = cls_decl.simp_name.id
self.copy_name_location (cls, cls_decl.simp_name)
self.enter (cls)
self.selectColor (cls, table = "classColors")
self.markDefn (cls)
self.markOutline (cls)
self.custom_class (cls_decl)
def on_open_class (self, cls_decl) :
cls = cls_decl.item_ref
self.custom_open_class (cls)
self.openScope (cls)
self.openCompletion (cls)
def on_close_class (self, cls_decl) :
cls = cls_decl.item_ref
self.closeCompletion (cls)
self.closeScope ()
def on_stop_class (self, cls_decl) :
# self.closeRegion ()
pass
# enum
def on_start_enum (self, enum_decl) :
enum = Enum ()
enum.link_code (enum_decl)
self.openRegion (enum) # region with background color
def on_enum (self, enum_decl) :
enum = enum_decl.item_ref
enum.item_name = enum_decl.simp_name.id
self.copy_name_location (enum, enum_decl.simp_name)
self.enter (enum)
self.selectColor (enum, table = "enumColors")
self.markDefn (enum)
self.markOutline (enum)
def on_open_enum (self, enum_decl) :
enum = enum_decl.item_ref
self.openScope (enum)
self.openCompletion (enum)
def on_enum_item (self, decl) :
item = EnumItem ()
item.item_name = decl.simp_name.id
item.link_code (decl)
self.copy_name_location (item, decl.simp_name)
self.enter (item)
self.selectColor (item, table = "variableColors")
self.markDefn (item)
def on_close_enum (self, enum_decl) :
enum = enum_decl.item_ref
self.closeCompletion (enum)
self.closeScope ()
def on_stop_enum (self, enum_decl) :
self.closeRegion ()
# typedef
def on_typedef (self, t) :
typedef = Typedef ()
typedef.link_code (t)
self.copy_declarator_name (typedef, t.decl)
self.copy_declarator_location (typedef, t.decl)
self.enter (typedef)
self.selectColor (typedef, table = "typedefColors")
self.markDefn (typedef)
self.markOutline (typedef)
# simple declaration
def on_simple_item (self, simple_declaration) :
simple_item = simple_declaration.items [-1] # get above simple declaration
variable = Variable ()
variable.link_code (simple_item)
variable.item_code_decl = simple_declaration # !?
"is it function"
func_spec = self.get_function_specifier (simple_item.decl)
if func_spec != None :
variable.is_function = True
variable.item_icon = "function"
self.copy_declarator_name (variable, simple_item.decl)
self.copy_declarator_location (variable, simple_item.decl)
init_type = simple_declaration.type_spec.item_type
variable.item_type = self.get_declarator_type (init_type, simple_item.decl)
"constructor or destructor"
if self.ctor_declarator (simple_item.decl) :
expr = simple_declaration.type_spec
if expr.kind == expr.simpleName :
func_name = expr.id
variable.item_name = func_name
cls = self.display [-1]
if isinstance (cls, Class) :
if func_name == cls.item_name :
variable.is_constructor = True
# if func_spec != None :
# if simple_declaration.a_destructor :
# variable.is_destructor = True
# else :
# variable.is_constructor = True
self.enter (variable)
if variable.is_function :
self.selectColor (variable, table = "functionColors")
else :
self.selectColor (variable, table = "variableColors")
self.markDefn (variable)
self.custom_simple_item (simple_declaration, simple_item)
def on_simple_declaration (self, simple_decl) :
self.custom_simple_declaration (simple_decl)
def on_simple_statement (self, stat) :
self.custom_simple_statement (stat)
def on_block_statement (self, stat) :
self.custom_block_statement (stat)
def ctor_declarator (self, decl) :
return ( decl.kind == decl.emptyDeclarator and
len (decl.ptr_spec.items) == 0 and
len (decl.cont_spec.items) == 1 and
isinstance (decl.cont_spec.items[0], CmmFunctionSpecifier))
def get_simple_name (self, qual_name) :
result = ""
if qual_name.kind == qual_name.simpleName :
result = qual_name.id
return result
def copy_declarator_name (self, target, declarator) :
if declarator != None :
while declarator.kind == declarator.nestedDeclarator :
declarator = declarator.inner_declarator
if declarator.kind == declarator.basicDeclarator :
target.item_name = self.get_simple_name (declarator.qual_name) # !?
else :
target.item_name = ""
def copy_declarator_location (self, target, declarator) :
if declarator != None :
while declarator.kind == declarator.nestedDeclarator :
declarator = declarator.inner_declarator
if declarator.kind == declarator.basicDeclarator :
self.copy_name_location (target, declarator.qual_name)
# function
def on_open_function (self, simple_declaration) :
if len (simple_declaration.items) != 0 : # !?
simple_item = simple_declaration.items [-1]
variable = simple_item.item_ref
if not variable.is_function :
self.openSearchOnlyScope (variable) # only for lookup, not for declarations
self.openCompletion (variable, outside = True)
if variable.is_function :
func = variable
self.openRegion (func) # region with background color
self.openScope (func)
func_spec = self.get_function_specifier (simple_item.decl)
self.enter_parameters (func_spec.parameters)
self.openCompletion (func, outside = True)
self.markOutline (func)
self.register (func, "(local)", func.local_scope)
func.local_scope.hidden_scope = True # do not print (local)
self.openScope (func.local_scope)
def on_close_function (self, simple_declaration) :
if len (simple_declaration.items) != 0 : # !?
simple_item = simple_declaration.items [-1]
variable = simple_item.item_ref
if not variable.is_function :
variable.item_body = simple_declaration.body
self.closeCompletion (variable, outside = True)
self.closeScope ()
if variable.is_function :
func = variable
func.item_body = simple_declaration.body
self.closeCompletion (func, outside = True)
self.closeScope () # local variables
self.closeScope () # parameters
self.closeRegion ()
# simple_declaration.body.item_label = func.item_name
self.custom_statement (variable, simple_declaration.body)
def get_function_specifier (self, declarator) :
result = None
while declarator != None and result == None :
inx = len (declarator.cont_spec.items) - 1
while inx >= 0 :
c = declarator.cont_spec.items [inx]
if isinstance (c, CmmFunctionSpecifier) :
result = c
inx = inx - 1
if result == None :
if declarator.kind == declarator.nestedDeclarator :
declarator = declarator.inner_declarator
else :
declarator = None
return result
def enter_parameters (self, param_list) :
for param in param_list.items :
if param.kind == param.plainParam : # !?
variable = Variable ()
variable.link_code (param)
self.copy_declarator_name (variable, param.decl)
self.copy_declarator_location (variable, param.decl)
init_type = getattr (param.type_spec, "item_type", None)
variable.item_type = self.get_declarator_type (init_type, param.decl)
self.enter (variable)
self.selectColor (variable, table = "variableColors")
self.markDefn (variable)
# names
def on_base_name (self, qual_name) :
decl = None
if qual_name.kind == qual_name.globalName :
inner_name = qual_name.inner_name
if inner_name.kind == inner_name.simpleName :
decl = self.searchScope (self.global_scope, inner_name.id)
else :
if qual_name.kind == qual_name.simpleName :
decl = self.lookup (qual_name.id)
if decl != None :
if isinstance (decl, Class) or isinstance (decl, Enum) or isinstance (decl, Typedef) :
qual_name.type_flag = True
# qual_name.item_type = self.get_type_decl (qual_name)
"add item_decl"
qual_name.item_decl = decl
self.custom_base_name (qual_name)
def is_template (self, qual_name) :
decl = qual_name.item_decl
result = decl != None and getattr (decl, "item_code", None) != None and getattr (decl.item_code, "template_decl", None) != None
return result
def is_cont_template (self, cont_name) :
return False
def on_template_args (self, qual_name) :
if qual_name.item_decl != None :
qual_name.item_qual = self.get_instance_identification (qual_name.item_decl)
self.create_instance (qual_name)
qual_name.item_decl = qual_name.left.item_decl # !?
def on_begin_compound_name (self, qual_name) :
self.remember_compound_name = qual_name
def on_cont_name (self, qual_name) :
decl = self.remember_compound_name
self.remember_compound_name = None
if decl != None and getattr (decl, "item_dict", None) != None :
qual_name.item_decl = self.searchScope (decl, qual_name.id)
def on_compound_name (self, qual_name) :
cont = qual_name.right
qual_name.item_decl = cont.item_decl
# type or expression
def is_binary_expression (self, expr) :
# type names cannot be left operand in binary expressions
return not expr.type_flag
def is_expression (self, expr) :
return not expr.type_flag
def is_value_parameter (self, expr) :
return not expr.type_flag
def on_begin_flexible_expr (self) :
# enable strange declarations (declaration starting with unknown identifier and asterisk)
self.enable_declaration_stack.append (True)
def on_end_flexible_expr (self) :
# disable strange declarations
self.enable_declaration_stack.pop ()
def on_name_expr (self, expr) :
# rember strange declaratrion flag and disable strange declarations
expr.remember_enable_declaration = self.enable_declaration_stack [-1]
self.enable_declaration_stack [-1] = False
def on_other_expr (self) :
# disable strange declarations
self.enable_declaration_stack [-1] = False
def is_multiplicative_expression (self, expr) :
return not expr.type_flag and not expr.remember_enable_declaration
def is_and_expression (self, expr) :
return not expr.type_flag and not expr.remember_enable_declaration
def on_bit_not_expr (self, expr) :
expr.type_flag = expr.param.type_flag
def is_postfix_expression (self, expr) :
if self.tokenText == "(" :
return True
# return not expr.type_flag and not expr.remember_enable_declaration
# return not expr.type_flag
else :
return not expr.type_flag
def is_mul (self, expr) :
return False
def is_add (self, expr) :
return False
def is_constructor (self, expr) :
return False
# location and style
def copy_location (self, target, source) :
target.src_file = source.src_file
target.src_line = source.src_line
target.src_column = source.src_column
target.src_pos = source.src_pos
target.src_end = source.src_end
def copy_name_location (self, target, qual_name) :
source = qual_name
if source != None :
if source.kind == source.compoundName :
source = source.right
self.copy_location (target, source)
def copy_style (self, target, source) :
if source != None :
if getattr (source, "item_ink", None) != None:
target.item_ink = source.item_ink
if getattr (source, "item_paper", None) != None:
target.item_paper = source.item_paper
if getattr (source, "item_icon", None) != None:
target.item_icon = source.item_icon
# name as a string
def get_name (self, qual_name) :
result = ""
if qual_name.kind == qual_name.simpleName :
result = qual_name.id
elif qual_name.kind == qual_name.specialName :
result = qual_name.spec_func.spec_name # !?
elif qual_name.kind == qual_name.compoundName :
result = self.get_name (qual_name.left) + "::" + self.get_name (qual_name.right)
elif qual_name.kind == qual_name.globalName :
result = "::" + self.get_name (qual_name.inner_name)
elif qual_name.kind == qual_name.destructorName :
result = "~" + self.get_name (qual_name.inner_name)
elif qual_name.kind == qual_name.templateName :
result = self.get_name (qual_name.left) + "<???>" # !?
if result == "" :
result = "???"
return result
# type specifiers
def on_type_name (self, expr) :
expr.type_flag = True
expr.item_type = expr.qual_name.item_type
def on_cv_specifier (self, expr) :
expr.type_flag = True
type = expr.param.item_type
if isinstance (type, NamedType) :
new_type = NamedType ()
new_type.type_const = type.type_const
new_type.type_volatile = type.type_volatile
new_type.type_name = type.type_name
new_type.type_decl = type.type_decl
if type != None : # !?
if expr.kind == expr.constSpec :
type.type_const = True
if expr.kind == expr.volatileSpec :
type.type_volatile = True
expr.item_type = type
def on_type_specifier (self, expr) :
expr.type_flag = True
type = self.get_type_spec (expr)
expr.item_type = type
self.copy_location (type, expr)
self.copy_style (type, expr)
# if isinstance (type, NamedType) :
# self.copy_style (type, type.type_decl)
# self.markUsage (type)
self.custom_type_specifiers (expr, type)
def get_type_decl (self, obj) :
result = None
if obj.item_decl != None :
if ( isinstance (obj.item_decl, Class) or
isinstance (obj.item_decl, Enum) or
isinstance (obj.item_decl, Typedef) or
isinstance (obj.item_decl, Unknown) ) :
result = obj.item_decl
return result
def get_named_type (self, qual_name) :
result = NamedType ()
result.type_name = self.get_name (qual_name)
result.type_decl = self.get_type_decl (qual_name)
if isinstance (qual_name, CmmTemplateName) :
result.type_name = self.get_name (qual_name.left) # !? name without < >
result.type_args = qual_name.template_args
result.type_args = [ ]
for arg in qual_name.template_args.items :
# type_spec = arg.value.type_spec
# result.type_args.append (type_spec.item_type) # !? missing pointers, ...
param = arg.value
init_type = getattr (param.type_spec, "item_type", None)
param_type = self.get_declarator_type (init_type, param.decl)
result.type_args.append (param_type)
return result
def get_type_spec (self, type_spec) :
result = None
# qual_name = type_spec.basic_name
# if qual_name != None :
# result = self.get_named_type (qual_name)
# else :
if 1 :
result = SimpleType ()
if type_spec.a_void : result.type_void = True
elif type_spec.a_bool : result.type_bool = True
elif type_spec.a_char : result.type_char = True
elif type_spec.a_wchar : result.type_wchar = True
elif type_spec.a_short : result.type_short = True
elif type_spec.a_int : result.type_int = True
elif type_spec.a_long : result.type_long = True
elif type_spec.a_float : result.type_float = True
elif type_spec.a_double : result.type_double = True
if type_spec.a_signed :
result.type_signed = True
elif type_spec.a_unsigned :
result.type_unsigned = True
# if type_spec.a_const :
# result.type_const = True
# if type_spec.a_volatile :
# result.type_volatile = True
return result
# declarator type
def get_declarator_type (self, init_type, declarator) :
result = init_type
while declarator != None :
for p in declarator.ptr_spec.items :
last = result
if p.kind == p.pointerSpec :
result = PointerType ()
result.type_from = last
if p.kind == p.referenceSpec :
result = ReferenceType ()
result.type_from = last
if p.cv_spec.cv_const :
result.type_const = True
if p.cv_spec.cv_volatile :
result.type_volatile = True
if declarator.kind != declarator.emptyDeclarator :
inx = len (declarator.cont_spec.items) - 1
while inx >= 0 :
c = declarator.cont_spec.items [inx]
last = result
if isinstance (c, CmmFunctionSpecifier) :
result = FunctionType ()
result.type_from = last
if isinstance (c, CmmArraySpecifier) :
result = ArrayType ()
result.type_from = last
inx = inx - 1
if declarator.kind == declarator.nestedDeclarator :
declarator = declarator.inner_declarator
else :
declarator = None
return result
# expression
def on_ident_expr (self, expr) :
self.markUsage (expr, expr.item_decl)
# !?
if self.get_type_decl (expr) != None :
expr.item_type = self.get_named_type (expr)
if expr.item_decl != None and getattr (expr.item_decl, "item_type", None) != None :
expr.item_type = expr.item_decl.item_type
"true or false"
if expr.kind == expr.simpleName :
ident = expr.id
if ident == "true" :
expr.item_value = True
elif ident == "false" :
expr.item_value = False
if hasattr (expr.item_decl, "item_value") :
expr.item_value = expr.item_decl.item_value
def on_field_expr (self, expr) :
left = expr.left
right = expr.simp_name
right.item_name = right.id
decl = None
if left.item_type != None :
decl = getattr (left.item_type, "type_decl", None)
elif left.item_decl != None :
decl = left.item_decl # class name or enum type name
if not isinstance (decl, Class) and not isinstance (decl, Enum) and not isinstance (decl, Typedef) :
decl = None
if decl != None and getattr (decl, "item_dict", None) != None :
right.item_decl = decl.item_dict.get (right.item_name)
# if expr.item_decl == None :
# self.warning ("Unknown field: " + expr.item_name)
expr.item_decl = right.item_decl
if getattr (right.item_decl, "item_type", None) != None : # !?.
expr.item_type = right.item_decl.item_type
self.markUsage (right, right.item_decl)
self.custom_field (expr)
def on_int_value (self, expr) :
expr.item_type = self.intType
text = expr.value
if text.startswith ("0") :
if text.startswith ("0x") :
expr.item_value = int (text[2:], 16)
elif text.startswith ("0b") :
expr.item_value = int (text[2:], 2)
elif text.startswith ("0o") :
expr.item_value = int (text[2:], 8)
elif text.startswith ("0q") :
expr.item_value = int (text[2:], 8)
elif len (text) > 1 :
expr.item_value = int (text[1:], 8) # starting zero => octal
else :
expr.item_value = 0
else:
expr.item_value = int (text)
def on_real_value (self, expr) :
expr.item_type = self.doubleType
expr.item_value = float (expr.value)
def on_char_value (self, expr) :
expr.item_type = self.charType
expr.item_value = expr.value
def on_string_value (self, expr) :
expr.item_type = self.stringType
text = expr.value
for item in expr.items :
text = text + item.value
expr.item_value = text
def on_call_expr (self, expr) :
self.custom_call (expr)
def on_binary_expr (self, expr) :
if expr.kind in [expr.mulExp, expr.divExp, expr.modExp,
expr.addExp, expr.subExp,
expr.shlExp, expr.shrExp,
expr.bitAndExp, expr.bitOrExp, expr.bitXorExp ] :
"result type"
a = self.type_number (expr.left)
b = self.type_number (expr.right)
inx = a
if b > inx :
inx = b
if inx == self.doubleInx :
expr.item_type = self.doubleType
if inx == self.floatInx :
expr.item_type = self.floatType
if inx == self.unsignedLongInx :
expr.item_type = self.unsignedLongType
if inx == self.longInx :
expr.item_type = self.longType
if inx == self.unsignedIntInx :
expr.item_type = self.unsignedIntType
if inx == self.intInx :
expr.item_type = self.intType
self.custom_binary (expr, inx)
elif expr.kind in [expr.ltExp, expr.leExp, expr.gtExp, expr.geExp, expr.eqExp, expr.neExp,
expr.logAndExp, expr.logOrExp ] :
expr.item_type = self.boolType
self.custom_relation (expr)
elif expr.kind in [expr.assignExp] :
self.custom_assign (expr)
self.binary_expr_value (expr)
# expression value
def get_expr_value (self, expr) :
return getattr (expr, "item_value", None)
def binary_expr_value (self, expr) :
value = None
if expr.kind in [ expr.addExp, expr.subExp, expr.mulExp, expr.divExp, expr.modExp,
expr.shlExp, expr.shrExp, expr.bitAndExp, expr.bitOrExp, expr.bitXorExp,
expr.ltExp, expr.gtExp, expr.leExp, expr.geExp, expr.eqExp, expr.neExp ] :
left = self.get_expr_value (expr.left)
right = self.get_expr_value (expr.right)
if left != None and right != None :
if expr.kind == expr.addExp : value = left + right
if expr.kind == expr.subExp : value = left - right
if expr.kind == expr.mulExp : value = left * right
if expr.kind == expr.divExp : value = left / right
if expr.kind == expr.modExp : value = left % right
if expr.kind == expr.shlExp : value = left << right
if expr.kind == expr.shrExp : value = left >> right
if expr.kind == expr.bitAndExp : value = left & right
if expr.kind == expr.bitOrExp : value = left | right
if expr.kind == expr.bitXorExp : value = left ^ right
if expr.kind == expr.ltExp : value = left < right
if expr.kind == expr.gtExp : value = left > right
if expr.kind == expr.leExp : value = left <= right
if expr.kind == expr.geExp : value = left >= right
if expr.kind == expr.eqExp : value = left == right
if expr.kind == expr.neExp : value = left != right
elif expr.kind == expr.logAndExp :
left = self.get_expr_value (expr.left)
if left != None :
if left == False :
value = False
else :
value = self.get_expr_value (expr.right)
elif expr.kind == expr.logOrExp :
left = self.get_expr_value (expr.left)
if left != None :
if left == True :
value = True
else :
value = self.get_expr_value (expr.right)
expr.item_value = value
# expression type
intInx = 1
unsignedIntInx = 2
longInx = 3
unsignedLongInx = 4
floatInx = 5
doubleInx = 6
unknownInx = 7
def init_types (self) :
self.intType = SimpleType ()
self.intType.type_int = True
self.unsignedIntType = SimpleType ()
self.unsignedIntType.type_unsigned = True
self.unsignedIntType.type_int = True
self.longType = SimpleType ()
self.longType.type_long = True
self.unsignedLongType = SimpleType ()
self.unsignedLongType.type_unsigned = True
self.unsignedLongType.type_long = True
self.floatType = SimpleType ()
self.floatType.type_float = True
self.doubleType = SimpleType ()
self.doubleType.type_double = True
self.boolType = SimpleType ()
self.boolType.type_bool = True
self.charType = SimpleType ()
self.charType.type_char = True
# self.wcharType = SimpleType ()
# self.wcharType.type_wchar = True
# self.voidType = SimpleType ()
# self.voidType.type_void = True
self.stringType = NamedType ()
self.stringType.type_name = "string" # !?
def type_number (self, expr) :
inx = self.unknownInx
type = expr.item_type
if type != None:
if isinstance (type, SimpleType) : # !?
if type.type_double :
inx = self.doubleInx
elif type.type_float :
inx = self.floatInx
elif type.type_long :
if type.type_unsigned :
inx = self.unsignedLongInx
else :
inx = self.longInx
elif type.type_int or type.type_short or type.type_wchar or type.type_char or type.type_bool :
if type.type_unsigned :
inx = self.unsignedIntInx
else :
inx = self.intInx
return inx
# -----------------------------------------------------------------------
def on_declaration_list (self, decl_list) :
if self.top_decl_list == None :
self.top_decl_list = decl_list
# -----------------------------------------------------------------------
def custom_namespace (self, ns_decl) :
pass
def custom_simple_item (self, simple_decl, simple_item) :
pass
def custom_simple_declaration (self, simple_decl) :
pass
def custom_simple_statement (self, stat) :
pass
def custom_block_statement (self, stat) :
pass
def custom_base_name (self, qual_name) :
pass
def custom_relation (self, expr) :
pass
def custom_binary (self, expr, inx) :
pass
def custom_assign (self, expr) :
pass
def custom_call (self, expr) :
pass
def custom_field (self, expr) :
pass
def custom_type_specifiers (self, type_spec, type) :
pass
def custom_statement (self, target, stat) :
pass
# --------------------------------------------------------------------------
class CmmQtCompiler (CmmCompiler) :
def __init__ (self) :
super (CmmQtCompiler, self).__init__ ()
self.foreign_modules = { }
self.foreign_types = { }
# -----------------------------------------------------------------------
# special scopes
def registerScope (self, top, name) :
if name in top.registered_scopes :
result = top.registered_scopes [name]
else :
result = Scope ()
result.hidden_scope = True
self.register (top, name, result)
return result
def enter_unknown (self, top, name, qual_name) :
scope = self.registerScope (top, "(unknown)")
if name in scope.item_dict :
unknown = scope.item_dict [name]
else :
unknown = Unknown ()
unknown.item_name = name
unknown.link_code (qual_name)
self.enterIntoScope (scope, unknown)
self.copy_location (unknown, qual_name)
unknown.item_ink = findColor ("unknown")
qual_name.item_decl = unknown
def enter_foreign (self, top, name, qual_name) :
scope = self.registerScope (top, "(foreign)")
# scope = top
if name in scope.item_dict :
result = scope.item_dict [name]
else :
result = Unknown ()
result.item_name = name
result.link_code (qual_name)
self.enterIntoScope (scope, result)
result.item_place = top # after enterIntoScope
self.copy_location (result, qual_name)
result.item_ink = findColor ("foreign")
qual_name.item_decl = result
# -----------------------------------------------------------------------
def find_foreign_object (self, name) :
result = None
for module in self.foreign_modules :
if result == None :
result = getattr (module, name, None)
# print ("FOUND", name, result)
# if name.startswith ("QTable") :
# print ("FOUND", name, result)
return result
def find_foreign_variable (self, var) :
type = var.item_type
if isinstance (type, PointerType) :
type = type.type_from
if isinstance (type, NamedType) :
name = type.type_name
var.foreign_obj = self.find_foreign_object (name) # variable with Qt type
# -----------------------------------------------------------------------
# custom identifiers
def custom_base_name (self, qual_name) :
if qual_name.item_decl == None and qual_name.kind == qual_name.simpleName :
name = qual_name.id
"foreign identifiers (Qt field names)"
inx = len (self.display) - 1
while qual_name.item_decl == None and inx >= 0 :
scope = self.display [inx]
if scope.foreign_obj != None :
if hasattr (scope.foreign_obj, name) :
self.enter_foreign (scope, name, qual_name)
# print ("QT item", name)
inx = inx - 1
stop = False
foreign = self.find_foreign_object (name) # variable with Qt type
if foreign != None :
# print ("FOREIGN", foreign.__name__)
self.enter_foreign (self.global_scope, name, qual_name)
if inspect.isclass (foreign) :
qual_name.type_flag = True
stop = True
if not stop :
"unknown identifiers"
inx = len (self.display) - 1
while qual_name.item_decl == None and inx >= 0 :
scope = self.display [inx]
if scope.default_scope :
self.enter_unknown (scope, name, qual_name)
# print ("UNKNOWN item", name)
inx = inx - 1
if qual_name.item_decl == None :
self.enter_unknown (self.global_scope, name, qual_name)
def custom_open_class (self, cls) :
base_list = cls.item_code.base_list
if base_list != None :
for item in base_list.items :
if cls.foreign_obj == None :
name = item.from_cls.id
cls.foreign_obj = self.find_foreign_object (name) # class with one/first Qt super class
# -----------------------------------------------------------------------
# Qt assign
def custom_assign (self, expr) :
var = expr.left.item_decl
right = expr.right
if var != None : # !?
self.find_foreign_variable (var)
name = var.item_name
target_obj = var.item_place.foreign_obj
context = var.item_context
if context.item_name == "(foreign)" : # !?
foreign = context.item_context.foreign_obj
if foreign != None :
set_name = "set" + name.capitalize ()
if hasattr (foreign, name) and hasattr (foreign, set_name) :
expr.alt_assign = set_name
if self.is_subtype (target_obj, "QTreeWidgetItem") :
if name == "text":
expr.alt_assign = "<text>"
elif name == "icon" :
expr.alt_assign = "<icon>"
elif name == "foreground" :
expr.alt_assign = "<foreground>"
elif name == "background" :
expr.alt_assign = "<background>"
else :
if name == "icon" :
expr.alt_assign = "<setIcon>"
elif name == "shortcut" :
expr.alt_assign = "<setShortcut>"
# -----------------------------------------------------------------------
# Qt field initialization
def find_type (self, name) :
result = None
if name in self.foreign_types :
result = self.foreign_types [name]
else :
for module in self.foreign_modules :
if result == None :
result = getattr (module, name, None)
self.foreign_types [name] = result # store type or None
return result
def is_subtype (self, obj, name) :
type = self.find_type (name)
result = obj != None and issubclass (obj, type)
return result
def custom_simple_item (self, simple_decl, simple_item) :
var = simple_item.item_ref
var.default_scope = True
self.find_foreign_variable (var)
type = var.item_type
type_name = ""
if isinstance (type, PointerType) :
type = type.type_from
if getattr (type, "type_name", "") != "" :
type_name = type.type_name
local_obj = var.foreign_obj
target_obj = None
if var.item_place != None :
target_obj = var.item_place.foreign_obj
if self.is_subtype (target_obj, "QMainWindow") :
if self.is_subtype (local_obj, "QMenuBar") :
var.alt_create = "<menuBar>"
elif self.is_subtype (local_obj, "QToolBar") :
var.alt_create = "<addToolBar>"
elif self.is_subtype (local_obj, "QStatusBar") :
var.alt_create = "<statusBar>"
elif self.is_subtype (local_obj, "QLayout") :
var.alt_setup = "<layout>"
else :
var.alt_setup = "<setCentralWidget>"
if var.alt_create == "" :
if self.is_subtype (local_obj, "QTreeWidgetItem") :
var.alt_create = type_name
var.alt_create_place = True
elif self.is_subtype (local_obj, "QTableWidgetItem") :
var.alt_create = type_name
elif self.is_subtype (local_obj, "QWidget") :
var.alt_create = type_name
var.alt_create_owner = True
elif self.is_subtype (local_obj, "QAction") :
var.alt_create = type_name
var.alt_create_owner = True
elif self.is_subtype (local_obj, "QLayout") :
var.alt_create = type_name
var.alt_create_owner = True
# if self.is_subtype (target_obj, "QMainWindow") :
# if self.is_subtype (local_obj, "QMenuBar") :
# pass
# elif self.is_subtype (local_obj, "QToolBar") :
# pass
# elif self.is_subtype (local_obj, "QStatusBar") :
# pass
# elif self.is_subtype (target_obj, "QLayout") :
if self.is_subtype (target_obj, "QLayout") :
if self.is_subtype (local_obj, "QLayout") :
var.alt_setup = "addLayout"
else :
var.alt_setup = "addWidget"
if self.is_subtype (target_obj, "QMenuBar") and self.is_subtype (local_obj, "QMenu") :
var.alt_setup = "addMenu"
elif self.is_subtype (local_obj, "QAction") :
var.alt_setup = "addAction"
elif self.is_subtype (target_obj, "QToolBar") or self.is_subtype (target_obj, "QStatusBar"):
var.alt_setup = "addWidget"
elif self.is_subtype (target_obj, "QTabWidget") :
var.alt_setup = "addTab"
var.alt_setup_param = quoteString (var.item_name) # !?
elif self.is_subtype (target_obj, "QTreeWidget") :
var.alt_setup = "addTopLevelItem"
elif self.is_subtype (target_obj, "QWidget") and self.is_subtype (local_obj, "QWidget") :
pass
elif target_obj != None and self.is_subtype (local_obj, "QWidget") :
var.alt_setup = "addWidget"
type = var.item_type
if isinstance (type, SimpleType) :
if type.type_bool :
var.alt_create = "<false>"
if type.type_char or type.type_wchar :
var.alt_create = "<char_zero>"
if type.type_short or type.type_int or type.type_long :
var.alt_create = "<zero>"
if type.type_float or type.type_double :
var.alt_create = "<real_zero>"
if isinstance (type, NamedType) :
if type.type_name == "string" :
var.alt_create = "<empty_string>"
if var.alt_create == "" :
var.alt_create = "<null>"
# -----------------------------------------------------------------------
"Qt connect"
def custom_block_statement (self, stat) :
expr = stat.inner_expr
if expr.kind == expr.callExp : # !?
if expr.left.kind == expr.simpleName : # !?
dcl = getattr (expr.left, "item_decl", None) # !?
if dcl != None :
foreign = dcl.item_context.foreign_obj
cls = self.getClass ()
if cls != None :
method = Method ()
method.name = "method" + str (len (cls.methods)+1)
method.body = stat.body
cls.methods.append (method)
expr.alt_connect = method.name
expr.alt_connect_dcl = dcl
expr.alt_connect_signal = expr.left.id
def getClass (self) :
inx = len (self.display) - 1
obj = None
while inx > 0 and obj == None :
tmp = self.display[inx]
if isinstance (tmp, Class) :
obj = tmp
else :
inx = inx - 1
return obj
# --------------------------------------------------------------------------
class CmmCustomCompiler (CmmQtCompiler) :
def __init__ (self) :
super (CmmCustomCompiler, self).__init__ ()
"options"
self.skip_functions = False
"type scope"
self.type_scope = self.registerScope (self.global_scope, "(type)")
"expr scope"
self.expr_cnt = 0
self.expr_scope = self.registerScope (self.global_scope, "(expr)")
"language extensions"
self.attribute_modules = [ ]
# -----------------------------------------------------------------------
def custom_field (self, expr) :
left = expr.left
right = expr.simp_name
"artificial fields"
if isinstance (left.item_decl, Class) :
if right.item_decl == None and right.item_name == "fields" :
"fields - list of variables declared in class"
fields = [ ]
for item in left.item_decl.item_list :
if isinstance (item, Variable) and not item.is_function :
fields.append (NoQuote (item.item_name))
expr.item_value = fields
# -----------------------------------------------------------------------
# special scopes
def enter_type (self, type) :
name = str (type)
if name in self.type_scope.item_dict :
decl = self.type_scope.item_dict [name]
self.copy_style (type, decl)
else :
type.item_name = name
self.enterIntoScope (self.type_scope, type)
self.selectColor (type)
# -----------------------------------------------------------------------
# attributes
def custom_namespace (self, ns_decl) :
"namespace_attributes"
ns = ns_decl.item_ref
for group in ns_decl.attr.items :
for a in group.items :
n = self.get_expr_name (a.attr_expr)
if n == "compile_time" :
ns.attr_compile_time = True
ns.skip_code = True
else :
self.error ("Unknown namespace attribute: " + n)
def custom_class (self, cls_decl) :
"class attributes"
cls = cls_decl.item_ref
for group in cls_decl.attr.items :
for a in group.items :
n = self.get_expr_name (a.attr_expr)
if n == "compile_time" :
cls.attr_compile_time = True
cls.skip_code = True
else :
self.error ("Unknown class attribute: " + n)
def custom_simple_item (self, simple_decl, simple_item) :
"invoke attribute"
if self.no_decl_spec (simple_decl.decl_spec) :
if not simple_decl.a_destructor :
expr = simple_decl.type_spec
if expr.kind == expr.simpleName : # !?
dcl = expr.item_decl
if dcl != None and isinstance (dcl, Variable):
if dcl.attr_compile_time :
if dcl.attr_field :
self.set_field (dcl.item_name)
else :
self.invoke_attribute (dcl.item_name)
decl = simple_item.decl # declarator
if decl.qual_name == None :
if len (decl.ptr_spec.items) == 0 :
if len (decl.ptr_spec.items) == 0 :
if len (decl.cont_spec.items) == 1 :
cont = decl.cont_spec.items [0]
if isinstance (cont, CmmFunctionSpecifier) :
values = [ ]
if not cont.cv_spec.cv_const :
if not cont.cv_spec.cv_volatile :
if cont.exception_spec == None :
params = cont.parameters
for param in params :
if (param.decl != None or
param.dots or
param.item_value == None) :
self.error ("Invalid attribute value")
values.append (param.item_value)
if dcl.attr_field :
self.set_field (dcl.item_name, values)
else :
self.invoke_attribute (dcl.item_name, values)
"simple item attributes"
var = simple_item.item_ref
for g in simple_item.attr.items :
for a in g.items :
n = self.get_expr_name (a.attr_expr)
if n == "compile_time" :
var.attr_compile_time = True
elif n == "field" :
var.attr_compile_time = True
var.attr_field = True
elif n == "context" :
var.attr_context = True
else :
self.error ("Unknown attribute: " + n)
if var.attr_compile_time :
if not var.attr_field :
self.check_attribute (simple_item)
var.skip_code = True
"Qt assign / declaration"
super (CmmCustomCompiler, self).custom_simple_item (simple_decl, simple_item)
def custom_simple_statement (self, stat) :
expr = stat.inner_expr
if expr.kind == expr.simpleName : # !?
dcl = expr.item_decl
if dcl != None and isinstance (dcl, Variable):
if dcl.attr_compile_time :
if dcl.attr_field :
self.set_field (dcl.item_name)
else :
self.invoke_attribute (dcl.item_name)
"Qt connect"
super (CmmCustomCompiler, self).custom_simple_statement (stat)
def no_decl_spec (self, decl_spec) :
return ( decl_spec == None or
( not decl_spec.a_inline and
not decl_spec.a_virtual and
not decl_spec.a_explicit and
not decl_spec.a_mutable and
not decl_spec.a_static and
not decl_spec.a_register ) )
def get_expr_name (self, expr) :
return self.get_name (expr)
def getContext (self) :
inx = len (self.display) - 1
obj = None
cont = True
while inx > 0 and cont :
obj = self.display[inx]
if ( isinstance (obj, Namespace) or
isinstance (obj, Enum) or
isinstance (obj, Class) or
isinstance (obj, Variable) ) :
cont = False
else :
inx = inx - 1
return obj
def set_field (self, name, value = True) :
ctx = self.getContext ()
setattr (ctx, name, value)
ctx.item_tooltip = "field " + name
self.info ("SET FIELD " + getattr (ctx, "item_name", "?") + "." + name + " = " + str (value))
def custom_call (self, expr) :
left = expr.left
if left.kind == left.simpleName : # !?
"attributes"
dcl = left.item_decl
if dcl != None and isinstance (dcl, Variable):
if dcl.attr_compile_time :
expr.skip_code = True
name = dcl.item_name
values = [ ]
if dcl.attr_context :
values.append (expr)
inx = 0
for param in expr.param_list.items :
inx = inx + 1
if dcl.attr_context : # !?
value = param
else :
if hasattr (param, "item_value") :
value = param.item_value
else :
value = None
self.error ("Unknown value of attribute parameter: " + name + " " + str (inx))
values.append (value)
self.invoke_attribute (name, values)
# -----------------------------------------------------------------------
def find_attribute (self, name) :
result = None
if hasattr (self, name) :
result = getattr (self, name)
if result == None :
for module in self.attribute_modules :
if result == None :
result = getattr (module, name, None)
if result == None :
self.error ("Missing attribute implementation: " + name)
return result
def check_attribute (self, decl) :
name = decl.item_ref.item_name
self.find_attribute (name) # only check
def invoke_attribute (self, name, arg_list = [ ]) :
obj = self.find_attribute (name)
if obj != None :
if callable (obj) :
self.info ("INVOKE " + name)
obj (*arg_list)