def create_typedef_vt(): d = Declaration() res = d.parse( ''' typedef struct _kc_Object Object; struct _kc_vt_Object { void (*clean)(Object *); int (*isKindOf)(Object *, const char *); int (*isKindOf)(Object *, Object *); int (*isInstanceOf)(Object *, const char *); int (*isInstanceOf)(Object *, Object *); }; ''') res2 = d.parse( ''' typedef struct _kc_Object Object; void clean(Object *); int isKindOf(Object *, const char *); int isKindOf(Object *, Object *); int isInstanceOf(Object *, const char *); int isInstanceOf(Object *, Object *); ''') res2.body.pop(0) for decl in res.body: if isinstance(decl._ctype, cnorm.nodes.ComposedType) and decl._ctype._identifier == '_kc_vt_Object': for (dcl, proto) in zip(decl._ctype.fields, res2.body): dcl._name = mangler.mimpleSangle(proto) global typedef_vt_object typedef_vt_object = decl
def add_legacy_fcts(self): d = Declaration() res = d.parse(""" typedef struct _kc_%s %s; void delete(%s*); """ % (self.ident, self.ident, self.ident)) decl = res.body[1] decl._name = mangler.muckFangle(decl, self.ident) setattr(decl, 'saved_name', 'delete') self.members.append(decl)
def add_new_proto(self, decl): d = Declaration() res = d.parse(""" typedef struct _kc_%s %s; %s *new(%s); """ % (self.ident, self.ident, self.ident, ', '.join([str(c.to_c()).rstrip() for c in decl._ctype.params]).replace(';', ''))) dcl = res.body[1] dcl._name = mangler.muckFangle(dcl, self.ident) setattr(decl, 'saved_name', 'new') self.protos.append(dcl)
def add_new_proto(self, decl): d = Declaration() res = d.parse(""" typedef struct _kc_%s %s; %s *new(%s); """ % (self.ident, self.ident, self.ident, ', '.join( [str(c.to_c()).rstrip() for c in decl._ctype.params]).replace(';', ''))) dcl = res.body[1] dcl._name = mangler.muckFangle(dcl, self.ident) setattr(decl, 'saved_name', 'new') self.protos.append(dcl)
def __init__(self, filename, path, importFiles=[], root=None): Grammar.__init__(self) Declaration.__init__(self) self.importFiles = importFiles self._rootref = root self._filename = filename self._path = path if 'KOOCPATH' not in environ: self.diagnostic.notify(error.Severity.ERROR, "please do 'export KOOCPATH=/home/$USER/rendu/kooc/.conf'") raise self.diagnostic factory = Declaration() res = factory.parse_file(environ["KOOCPATH"] + '/builtins_class.kp') self._classTemplate = deepcopy(res.body) res = factory.parse_file(environ["KOOCPATH"] + '/builtins_implem.kp') self._implemTemplate = deepcopy(res.body)
def instanciate_vtable(): global implementations d = Declaration() res = d.parse(""" typedef struct _kc_Object Object; typedef struct _kc_vt_Object vt_Object; vt_Object vtable_Object = {&clean, &isKindOf, &isKindOf, &isInstanceOf, &isInstanceOf}; """) for decl in res.body: if hasattr(decl, '_name') and decl._name == 'vtable_Object': for (elem, imp) in zip(decl._assign_expr.body, implementations[0].imps): elem.params[0].value = imp._name global obj_vtable obj_vtable = decl return decl return None
def implement_vtable(ast, module): vtable = Declaration().parse("vtable_for_" + module.name + "={};").body[0] vtable._ctype._identifier = module.name + "Vtable" vtable._assign_expr.body.append(Literal('"' + get_name(module) + '"')) for it in module.functions: if it.isVirtual: vtable._assign_expr.body.append(Literal(it.mangle())) ast.ref.body.append(vtable)
def create_alloc_fct(self): d = Declaration() res = d.parse(""" typedef struct _kc_%s %s; %s *alloc() { %s *self; self = malloc(sizeof(%s)); return (self); } """ % (self.ident, self.ident, self.ident, self.ident, self.ident)) for decl in res.body: if isinstance(decl._ctype, cnorm.nodes.FuncType): decl._name = mangler.muckFangle(decl, self.ident) self.alloc_fct = decl self.imps.append(decl)
def new_scope(self): from kooc import glist global glist global scope global isscope global decl from mangle import mangle from implementation import implement isscope = True scope = decl if not hasattr(glist, scope): glist[scope] = [] if implement["type"] == "CM": parse = Declaration() nod = parse.parse("struct " + implement["name"] + " * self;") glist[scope].append(mangle(nod.body[0], "nonename", "M")) return True
def add_funcs(ast, module): ast.ref.body.append( new_func("void", "malloc", PointerType(), new_primary("unsigned long", "size"))) ast.ref.body.append( new_func("void", "free", None, new_primary("void", "ptr", PointerType()))) for it in module.functions: if it.module() == module and it._name in ("alloc", "delete", "init", "new"): decl = Decl(it.mangle(), it._ctype) if it._name == "alloc": decl.body = Declaration().parse("{return malloc(sizeof(" + module.name + "));}").body[0].body ast.ref.body.append(decl) elif it._name == "delete": func = "{" func_clean = module.getFuncs("clean") if len(func_clean) == 1: func += func_clean[0].mangle() + "(self);" elif len(func_clean) > 1: sys.exit("Module " + module._name + "has more than 1 function clean.") func += "free(self);}" decl.body = Declaration().parse(func).body[0].body ast.ref.body.append(decl) elif it._name == "init" and hasattr(it, "default_init"): decl.body = BlockStmt([]) ast.ref.body.append(decl) elif it._name == "new": init = get_init_func(module, it) func = """\ { """ + module.name + """ * inst; inst = """ + module.getFuncs("alloc")[0].mangle() + """(); """ + init.mangle() + """(); return inst; }""" decl.body = Declaration().parse(func).body[0].body for var in init._ctype.params: decl.body.body[2].expr.params.append(Id(var._name)) decl.body.body[2].expr.params[0].value = "inst" ast.ref.body.append(decl)
def class__init(self, ast, _type, i): module = Module(self.value(i)) if self.value(_type) == "@class": if module.name != "Object" and "Object" not in symtab: atimport.hooks.do_import(ast, "Object.kh") if Status.parent != None: inherit_module(module, Status.parent) else: if self.value(i) != "Object": inherit_module(module, "Object") else: self.parent = None module.isClass = True Status.module = Status.CLASS if module.parent: module.node = Declaration().parse("typedef int " + module.parent.name + ";typedef struct{" + module.parent.name + " parent;}" + module.name + ";").body[1] else: module.node = Declaration().parse("typedef struct{void* vtable;}" + module.name + ";").body[0] ast.ref.body.append(module.node) ast.ref.types[module.name] = weakref.ref(module.node) add_func_proto(ast.ref.body, module, new_func(module.name, "alloc", PointerType()), False) add_func_proto( ast.ref.body, module, new_func("void", "delete", None, new_primary(module.name, "self", PointerType())), True) ast.ref.body.append( Raw("#define VTABLE_" + module.name + "(self) ((" + module.name + "Vtable*)self)\n")) else: Status.module = Status.MODULE symtab[module.name] = module Status.moduleName = module.name return True
def create_decl_malloc(self, inheri): size = len(inheri) lDecl = [] d = Declaration() res = d.parse( """ typedef struct _kc_Object Object; typedef struct _kc_%s %s; void dummy() { %s* self; ((Object *)self)->vt = &vtable_%s; ((Object *)self)->inheritance = malloc((%d + 1) * sizeof(char *)); ((Object *)self)->inheritance[%d] = "YOLO"; ((Object *)self)->inheritance[%d] = 0; } """ % (self.ident, self.ident, self.ident, self.ident, size, size, size)) for decl in res.body: if hasattr(decl, '_name') and decl._name == 'dummy': for dcl in decl.body.body: if isinstance(dcl, cnorm.nodes.ExprStmt): if isinstance( dcl.expr.params[len(dcl.expr.params) - 1], cnorm.nodes.Literal): if dcl.expr.params[len(dcl.expr.params) - 1].value == '0': declNull = dcl else: declToChange = dcl else: lDecl.append(dcl) declTmp = declToChange for idx, decl in enumerate(inheri): for dcl in declTmp.expr.params: if isinstance(dcl, cnorm.nodes.Literal): dcl.value = ("\"" + decl + "\"") declTmp.expr.params[0].params[0].value = str(idx) lDecl.append(deepcopy(declTmp)) lDecl.append(declNull) return lDecl
def create_delete_fct(self): d = Declaration() res = d.parse(""" typedef struct _kc_Object Object; typedef struct _kc_%s %s; typedef struct _kc_vt_%s vt_%s; void delete(%s *self) { ((vt_%s*)((Object*)self)->vt)->clean(self); } """ % (self.ident, self.ident, self.ident, self.ident, self.ident, self.ident)) for decl in res.body: if isinstance(decl._ctype, cnorm.nodes.FuncType): decl._name = mangler.muckFangle(decl, self.ident) for dcl in decl.body.body: if hasattr(dcl.expr, 'call_expr') and hasattr(dcl.expr.call_expr, 'params') \ and dcl.expr.call_expr.params[0].value == 'clean': dcl.expr.call_expr.params[0].value = 'clean$$void' self.imps.append(decl)
def create_new_fct(self, ini): params = [] if len(ini._ctype._params) >= 1: params = ini._ctype._params[1:] d = Declaration() res = d.parse(""" typedef struct _kc_Object Object; typedef struct _kc_%s %s; %s *new(%s) { %s* self; self = alloc(); init(self, %s); ((Object*)self)->name = "%s"; return (self); } """ % (self.ident, self.ident, self.ident, ', '.join( [str(c.to_c()).rstrip() for c in params]).replace(';', ''), self.ident, ', '.join( [c._name for c in params]), self.ident)) for decl in res.body: if hasattr(decl, '_name') and decl._name == 'new': decl._name = mangler.muckFangle(decl, self.ident) decl.body.body[4:4] = self.create_decl_malloc( self.get_inheritance(self.ident, [])) for dcl in decl.body.body: if isinstance(dcl, cnorm.nodes.ExprStmt): if isinstance(dcl.expr, cnorm.nodes.Binary) and\ (isinstance(dcl.expr.params[0], cnorm.nodes.Arrow) or \ isinstance(dcl.expr.params[0], cnorm.nodes.Array)): pass elif isinstance(dcl.expr, cnorm.nodes.Binary): dcl.expr.params[ 1].call_expr.value = self.alloc_fct._name elif isinstance(dcl.expr, cnorm.nodes.Func): dcl.expr.call_expr.value = ini._name self.imps.append(decl)
def create_new_fct(self, ini): params = [] if len(ini._ctype._params) >= 1: params = ini._ctype._params[1:] d = Declaration() res = d.parse(""" typedef struct _kc_Object Object; typedef struct _kc_%s %s; %s *new(%s) { %s* self; self = alloc(); init(self, %s); ((Object*)self)->name = "%s"; return (self); } """ % (self.ident, self.ident, self.ident, ', '.join([str(c.to_c()).rstrip() for c in params]).replace(';', ''), self.ident, ', '.join([c._name for c in params]), self.ident)) for decl in res.body: if hasattr(decl, '_name') and decl._name == 'new': decl._name = mangler.muckFangle(decl, self.ident) decl.body.body[4:4] = self.create_decl_malloc(self.get_inheritance(self.ident, [])) for dcl in decl.body.body: if isinstance(dcl, cnorm.nodes.ExprStmt): if isinstance(dcl.expr, cnorm.nodes.Binary) and\ (isinstance(dcl.expr.params[0], cnorm.nodes.Arrow) or \ isinstance(dcl.expr.params[0], cnorm.nodes.Array)): pass elif isinstance(dcl.expr, cnorm.nodes.Binary): dcl.expr.params[1].call_expr.value = self.alloc_fct._name elif isinstance(dcl.expr, cnorm.nodes.Func): dcl.expr.call_expr.value = ini._name self.imps.append(decl)
def add_call(self, call, mod, var, spe): from kooc import mlist, clist, slist, glist from drecovery import scope global mlist global slist global clist global glist global scope scope_list = [] type_object = "" ptr = "" if mod.value in mlist: scope_list = mlist type_object = "M" elif mod.value in clist: scope_list = clist type_object = "C" else: tmp = None for item in glist[scope]: if item["name"] == mod.value and len(item["type"]) > 3 and item["type"][:3] == "2Sp": if item["type"][3:] in clist: tmp = item break if tmp == None: print_error("error no module called : " + mod.value) return False scope_list = slist ptr = mod.value + "->" mod.value = tmp["type"][3:] type_object = "CM" if spe.value == "": return algo(call, mod, var, scope_list, ptr) else: cparse = Declaration() ast = cparse.parse(spe.value + " " + var.value + ";") m = mangle(ast.body[0], mod.value, type_object)["mangle"] return algo_spe(call, mod, var, m, scope_list, ptr) return True
def new_dcl(self, decl): from kooc import glist, mlist, clist, vlist from copy import deepcopy from mangle import mangle from implementation import implement global glist global scope global isscope global implement if isscope == True and implement["name"] != "": m = mangle(decl.node, implement["name"], implement["type"]) test = clist if implement["type"] == "M": test = mlist if implement["type"] == "CM": parse = Declaration() nod = parse.parse("struct " + implement["name"] + " * self;") decl.node._ctype._params.append(nod.body[0]) test = vlist found = False for item in test[implement["name"]]: if item["mangle"] == m["mangle"]: found = True if found == False: print_error("Error function not declared :" + implement["name"] + " " + m["name"]) return False else: tmp = deepcopy(decl) m = mangle(tmp.node, "nonename", "M") for item in glist[scope]: if item["mangle"].split("_")[3] == "F": if item["mangle"] == m["mangle"]: return True glist[scope].append(m) isscope = False return True
def create_vtable(module, stmt): if module.parent: vtable = copy.deepcopy(module.parent.vtable) vtable._name = module.name + "Vtable" else: vtable = Declaration().parse("typedef struct{char* name;}" + module.name + "Vtable;").body[0] for it in module.functions: if it.isVirtual and it.module() == module and ( not module.parent or it.getFromParent(module.parent) == None): vtable._ctype.fields.append( func_to_ptr(Decl(it.getString(), it._ctype))) stmt.append(vtable) module.vtable = vtable
def create_decl_malloc(self, inheri): size = len(inheri) lDecl = [] d = Declaration() res = d.parse(""" typedef struct _kc_Object Object; typedef struct _kc_%s %s; void dummy() { %s* self; ((Object *)self)->vt = &vtable_%s; ((Object *)self)->inheritance = malloc((%d + 1) * sizeof(char *)); ((Object *)self)->inheritance[%d] = "YOLO"; ((Object *)self)->inheritance[%d] = 0; } """ % (self.ident, self.ident, self.ident, self.ident, size, size, size)) for decl in res.body: if hasattr(decl, '_name') and decl._name == 'dummy': for dcl in decl.body.body: if isinstance(dcl, cnorm.nodes.ExprStmt): if isinstance(dcl.expr.params[len(dcl.expr.params) - 1], cnorm.nodes.Literal): if dcl.expr.params[len(dcl.expr.params) - 1].value == '0': declNull = dcl else: declToChange = dcl else: lDecl.append(dcl) declTmp = declToChange for idx, decl in enumerate(inheri): for dcl in declTmp.expr.params: if isinstance(dcl, cnorm.nodes.Literal): dcl.value = ("\"" + decl + "\"") declTmp.expr.params[0].params[0].value = str(idx) lDecl.append(deepcopy(declTmp)) lDecl.append(declNull) return lDecl
def mangle_func(self, call, spe, mod, var, params): from kooc import mlist, clist, glist, vlist from drecovery import scope from listToStr import listToListStr global mlist, clist, glist, scope, vlist scope_list = [] type_object = "" ptr = "" nnname = "" if mod.value in mlist: scope_list = mlist type_object = "M" elif mod.value in clist: scope_list = clist type_object = "C" else: tmp = None for item in glist[scope]: if item["name"] == mod.value and len(item["type"]) > 3 and item["type"][:3] == "2Sp": if item["type"][3:] in clist: tmp = item break if tmp == None: print_error("error no module called : " + mod.value) return False scope_list = vlist ptr = "(((struct vtable_" + tmp["type"][3:] + " *)" + mod.value + ")-1)->" nnname = mod.value mod.value = tmp["type"][3:] type_object = "CM" cparse = Declaration() list_params = [] all_params = [""] found = False if hasattr(params, "node"): for item in params.node: if "<class 'cnorm.nodes.Func'>" != str(type(item)): tmp = resolve(item, [mlist, clist]) else: tmp = resolve(item.call_expr, [mlist, clist]) if tmp == []: print_error("Error ambiguious statement") return False list_params.append(tmp) all_params = listToListStr(list_params) for item in all_params: if spe.value == "": m = mangle_func_from(mod.value, type_object, var.value, None, item) res = func_algo(call, mod, var, m, scope_list, ptr) else: ast = cparse.parse(spe.value + " " + var.value + "()" ";") m = mangle_func_from(mod.value, type_object, var.value, ast.body[0], item) res = func_algo_spe(call, mod, var, m, scope_list, ptr) if res == True and found == True: print_error("ambiguious function : " + mod.value + " " + var.value) return False if res == True: found = True if found == False: print_error("Don't found function : " + mod.value + " " + var.value) return False if not hasattr(params, "node"): params.node = [] if nnname != "": params.node.append(nodes.Id(nnname)) return True
class UnittestModule(unittest.TestCase): def setUp(self): self.cparse = Declaration() self.kparse = KoocG() def tearDown(self): self.cparse = None self.kparse = None KoocFile.debugCleanAll() if hasattr(self, "res") and not hasattr(self.res, "to_c"): self.assertFalse(self.res.diagnostic.get_content()) ## SIMPLE TO MORE COMPLEX TEST OF VALIDS MODULES def test_empty_module(self): self.res = self.kparse.parse(""" @module Test { } """) self.assertEqual(str(self.res.to_c()), "") def test_declaration_variable(self): self.res = self.kparse.parse(""" @module Test { void test; } """) self.assertEqual(str(self.res.to_c()), "extern void M4Test__v4test;\n") def test_declaration_assignement_variable(self): self.res = self.kparse.parse(""" @module Test { int test = 42; } """) self.assertEqual(str(self.res.to_c()), "extern int M4Test__i4test;\n") def test_declaration_function_implicit_void(self): self.res = self.kparse.parse(""" @module Test { void test(); } """) self.assertEqual(str(self.res.to_c()), "extern void M4Test__v4testv();\n") def test_declaration_function_explicit_void(self): self.res = self.kparse.parse(""" @module Test { void test(void); } """) self.assertEqual(str(self.res.to_c()), "extern void M4Test__v4testv(void);\n") def test_declaration_function(self): self.res = self.kparse.parse(""" @module Test { char *test(int **toto, float tata[]); } """) self.assertEqual( str(self.res.to_c()), "extern char *M4Test__Pc4testPPiAf(int **toto, float tata[]);\n") def test_variable_overload(self): self.res = self.kparse.parse(""" @module Mayuri { int tuturu; float tuturu; } """) self.assertEqual( str(self.res.to_c()), "extern int M6Mayuri__i6tuturu;\nextern float M6Mayuri__f6tuturu;\n" ) def test_variable_and_function_with_no_param(self): self.res = self.kparse.parse(""" @module Mayuri { int tuturu; int tuturu(); } """) self.assertEqual( str(self.res.to_c()), "extern int M6Mayuri__i6tuturu;\nextern int M6Mayuri__i6tuturuv();\n" ) def test_function_return_value_overload(self): self.res = self.kparse.parse(""" @module Mayuri { int tuturu(float toto); float tuturu(float tutu); } """) self.assertEqual( str(self.res.to_c()), "extern int M6Mayuri__i6tuturuf(float toto);\n\ extern float M6Mayuri__f6tuturuf(float tutu);\n") def test_function_params_value_overload(self): self.res = self.kparse.parse(""" @module Mayuri { double **tuturu(char toto[], void* ptr[]); double** tuturu(int tutu); } """) self.assertEqual( str(self.res.to_c()), "extern double **M6Mayuri__PPd6tuturuAcAPv(char toto[], void *ptr[]);\n\ extern double **M6Mayuri__PPd6tuturui(int tutu);\n") ## TODO : TESTS WITH SOME FUNCTION POINTER ## TEST OF OVERLOADS WITH DIFFERENTS STORAGES, QUALIFIERS OR SPECIFIER def test_auto_variable(self): waited = self.cparse.parse(""" extern auto int M4Test__i4test; """) self.res = self.kparse.parse(""" @module Test { auto int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_register_variable(self): waited = self.cparse.parse(""" extern register int M4Test__i4test; """) self.res = self.kparse.parse(""" @module Test { register int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_typedef_variable(self): waited = self.cparse.parse(""" extern typedef int M4Test__i4test; """) self.res = self.kparse.parse(""" @module Test { typedef int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_static_variable(self): waited = self.cparse.parse(""" extern static int M4Test__i4test; """) self.res = self.kparse.parse(""" @module Test { static int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_extern_variable(self): waited = self.cparse.parse(""" extern extern int M4Test__i4test; """) self.res = self.kparse.parse(""" @module Test { extern int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_inline_variable(self): with self.assertRaises(KoocException) as cm: print( self.kparse.parse(""" @module Test { inline int test; } """)) # def test_virtual_variable(self): # waited = self.cparse.parse(""" # extern virtual int M4Test__i4test; # """) # self.res = self.kparse.parse( # """ # @module Test # { # virtual int test; # } # """) # self.assertEqual(str(self.res.to_c()), str(waited.to_c())) # def test_explicit_variable(self): # waited = self.cparse.parse(""" # extern explicit int M4Test__i4test; # """) # self.res = self.kparse.parse( # """ # @module Test # { # explicit int test; # } # """) # self.assertEqual(str(self.res.to_c()), str(waited.to_c())) # def test_forceinline_variable(self): # waited = self.cparse.parse(""" # extern forceinline int M4Test__i4test; # """) # self.res = self.kparse.parse( # """ # @module Test # { # forceinline int test; # } # """) # self.assertEqual(str(self.res.to_c()), str(waited.to_c())) # def test_thread_variable(self): # waited = self.cparse.parse(""" # extern thread int M4Test__i4test; # """) # self.res = self.kparse.parse( # """ # @module Test # { # thread int test; # } # """) # self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_volatile_variable(self): waited = self.cparse.parse(""" extern volatile int M4Test__V_i4test; """) self.res = self.kparse.parse(""" @module Test { volatile int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_restrict_variable(self): waited = self.cparse.parse(""" extern restrict int M4Test__R_i4test; """) self.res = self.kparse.parse(""" @module Test { restrict int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_long_variable(self): waited = self.cparse.parse(""" extern long int M4Test__li4test; """) self.res = self.kparse.parse(""" @module Test { long int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_long_long_variable(self): waited = self.cparse.parse(""" extern long long int M4Test__lli4test; """) self.res = self.kparse.parse(""" @module Test { long long int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_short_variable(self): waited = self.cparse.parse(""" extern short int M4Test__si4test; """) self.res = self.kparse.parse(""" @module Test { short int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_const_ptr_variable(self): waited = self.cparse.parse(""" extern const int *M4Test__PC_i4test; """) self.res = self.kparse.parse(""" @module Test { int const* test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_complex_variable(self): self.res = self.kparse.parse(""" @module Test { auto unsigned int const* const* test; } """) waited = self.cparse.parse(""" extern auto unsigned int const* const* M4Test__PC_PC_Ui4test; """) self.assertEqual(str(self.res.to_c()), str(waited.to_c()))
def setUp(self): self.cparse = Declaration() self.kparse = KoocG()
#!/usr/bin/env python3 from pyrser.grammar import Grammar from pyrser import meta from cnorm import nodes from cnorm.parsing.declaration import Declaration from KoocGrammar.KC_Statement import KC_Statement from cnorm.parsing.expression import Idset from cnorm.nodes import * from mangler.simple_mangling import VARS import knodes import KoocFile gr = Declaration() class Class(Grammar, KC_Statement): entry = 'class' grammar = """ class = [ "@class" Class.Name:class_name #add_class_to_type(class_name) class_single_statement:body #add_class(current_block, class_name, body) ] class_single_statement = [ [ class_compound_statement ]:>_ ] class_compound_statement = [ [
parser.add_argument( "-d", "--dump", dest="dump", help="show AST nodes as vars", action='store_true' ) parser.add_argument( "-p", "--parse", dest="parse", help="only parsing", action='store_true' ) args = parser.parse_args() for f in args.filenames: if f != '-' and os.path.exists(f): cparse = Declaration() ast = cparse.parse_file(f) if args.dump: print(vars(ast)) if args.yml: print(ast.to_yml()) if ast: if not args.parse: print(ast.to_c()) else: print("something goes wrong")
class UnittestKooccall(unittest.TestCase): def setUp(self): self.cparse = Declaration() self.kparse = KoocG() def tearDown(self): self.cparse = None self.kparse = None KoocFile.debugCleanAll() if hasattr(self, "res") and not hasattr(self.res, "to_c"): self.assertFalse(self.res.diagnostic.get_content()) def test_simple_function_call(self): self.res = self.kparse.parse( """ @module Test { int test(void); } int main() { [Test test]; } """) waited = self.cparse.parse(""" extern int M4Test__i4testv(void); int main() { M4Test__i4testv(); } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_simple_variable_call(self): self.res = self.kparse.parse( """ @module Test { int test; } int main() { [Test.test]; } """) waited = self.cparse.parse(""" extern int M4Test__i4test; int main() { M4Test__i4test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_complex_variable_call(self): self.res = self.kparse.parse( """ @module Test { auto unsigned int const* const* test; } int main() { [Test.test]; } """) #TODO : c'est quoi le mangling de cette merde ? waited = self.cparse.parse(""" extern const unsigned int *const *M4Test__PC_PC_Ui4test; int main() { M4Test__PC_PC_Ui4test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) # def test_simple_variable_call(self): # self.res = self.kparse.parse( # """ # int main() # { # [Test.test]; # } # """) # print(res.diagnostic.get_content()) # waited = self.cparse.parse(""" # M4Test__i4test; # """).to_c()) # print("RESULT = ", res, "\n") # print("WAITED = ", waited, "\n") # self.assertEqual(res, waited) def test_simple_variable_assign_call(self): self.res = self.kparse.parse( """ @module Test { int test; } int main() { int a = [Test.test]; } """) waited = self.cparse.parse(""" extern int M4Test__i4test; int main() { int a = M4Test__i4test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_function_one_arg_call(self): self.res = self.kparse.parse( """ @module Test { int test(int toto); } int main() { [Test test :(int)42]; } """) waited = self.cparse.parse(""" extern int M4Test__i4testi(int toto); int main() { M4Test__i4testi(42); } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_function_one_arg_call_invalid_arg_type(self): self.res = self.kparse.parse( """ @module Test { int test(int toto); } int main() { [Test test :(invalid)42]; } """) waited = self.cparse.parse(""" extern int M4Test__i4testi(int toto); int main() { M4Test__i4testi(42); } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_function_two_arg_call(self): self.res = self.kparse.parse( """ @module Titor { void send_dmail(void *this, char *mail); } int main() { char *mail = "Watashi wa mad scientist !"; @!(void)[Titor send_dmail :(void *)0 :(char *)mail]; } """) waited = self.cparse.parse(""" extern void M5Titor__v10send_dmailPvPc(void *this, char *mail); int main() { char *mail = "Watashi wa mad scientist !"; M5Titor__v10send_dmailPvPc(0, mail); } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_function_return_type_inferred_call(self): self.res = self.kparse.parse( """ @module Titor { void send_dmail(void *this, char *mail); void send_dmail(char *mail); } int main() { char *mail = "Watashi wa mad scientist !"; [Titor send_dmail :(void *)0 :(char *)mail]; } """) waited = self.cparse.parse(""" extern void M5Titor__v10send_dmailPvPc(void *this, char *mail); extern void M5Titor__v10send_dmailPc(char *mail); int main() { char *mail = "Watashi wa mad scientist !"; M5Titor__v10send_dmailPvPc(0, mail); } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_function_empty_params_types_inferred_call(self): self.res = self.kparse.parse( """ @module Titor { char *get_dmail(void); } //@implementation Titor { char *get_dmail(void) {return "tutu";} } int main() { printf("%s\n", @!(char *)[Titor get_dmail]); } """) waited = self.cparse.parse(""" extern char* M5Titor__Pc9get_dmailv(void); int main() { printf("%s\n", M5Titor__Pc9get_dmailv()); } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_function_int_params_types_inferred_call(self): self.res = self.kparse.parse( """ @module Titor { char *get_dmail(int index); void *get_dmail(int index); } int main() { printf("%s\n", @!(char *)[Titor get_dmail :42]); } """) waited = self.cparse.parse(""" extern char* M5Titor__Pc9get_dmaili(int index); extern void* M5Titor__Pv9get_dmaili(int index); int main() { printf("%s\n", M5Titor__Pc9get_dmaili(42)); } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_function_all_inferred_call(self): self.res = self.kparse.parse( """ @module Titor { char *get_dmail(int index); } int main() { printf("%s\n", [Titor get_dmail :42]); } """) waited = self.cparse.parse(""" extern char* M5Titor__Pc9get_dmaili(int index); int main() { printf("%s\n", M5Titor__Pc9get_dmaili(42)); } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_function_overload_charptr_call(self): self.res = self.kparse.parse( """ @module Titor { char *get_dmail(int index); float get_dmail(int index); } int main() { printf("%s\n", @!(char *)[Titor get_dmail :(int)42]); } """) waited = self.cparse.parse( """ extern char* M5Titor__Pc9get_dmaili(int index); extern float M5Titor__f9get_dmaili(int index); int main() { printf("%s\n", M5Titor__Pc9get_dmaili(42)); } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_function_overload_floatcall(self): self.res = self.kparse.parse( """ @module Titor { char *get_dmail(int index); float get_dmail(int index); } int main() { printf("%s\n", @!(float)[Titor get_dmail :(int)42]); } """) waited = self.cparse.parse( """ extern char* M5Titor__Pc9get_dmaili(int index); extern float M5Titor__f9get_dmaili(int index); int main() { printf("%s\n", M5Titor__f9get_dmaili(42)); } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_function_impossible_inferred_return_type(self): with self.assertRaises(RuntimeError) as cm: print(self.kparse.parse( """ @module Titor { char *get_dmail(int index); float get_dmail(int index); } int main() { printf("%s\n", [Titor get_dmail :(int)42]); } """)) def test_function_impossible_inferred_params_type(self): with self.assertRaises(RuntimeError) as cm: print(self.kparse.parse( """ @module Titor { char *get_dmail(int index); char *get_dmail(float date); } int main() { printf("%s\n", [Titor get_dmail :42]); } """))
def getPrimaryType(param): decl = Declaration() typ = decl.parse(param + ';').body[0]._ctype return typ
def update_type(self, ast, typ): decl = Declaration() ast.typ = decl.parse(self.value(typ) + ';').body[0]._ctype return True
def add_cl(self, ast, ret): from cnorm import nodes from copy import deepcopy global clist global mlist global vlist if ret.mname in mlist or ret.mname in clist: print_error("Error module or class already declared : " + ret.mname) return False if not ret.mname in clist: clist[ret.mname] = [] for item in ret.node.body: clist[ret.mname].append(mangle(item, ret.mname, "C")) ast.node.body.extend(ret.node.body) test = "<class \'cnorm.nodes.FuncType\'>" private_var = [ item for item in ret.private.body if str(type(item._ctype)) != test ] private_func = [ item for item in ret.private.body if str(type(item._ctype)) == test ] if not hasattr(slist, ret.mname): slist[ret.mname] = [] for item in private_var: slist[ret.mname].append(mangle(item, ret.mname, "CM")) st = nodes.Decl(ret.mname) st._ctype = nodes.ComposedType(ret.mname) st._ctype._specifier = 1 st._ctype._storage = 2 st._ctype.fields = private_var ast.node.body.append(st) if not hasattr(vlist, ret.mname): vlist[ret.mname] = [] parse = Declaration() nod = parse.parse("struct " + ret.mname + " * self;") for item in private_func: vlist[ret.mname].append(mangle(item, ret.mname, "CM")) item._ctype._params.append(nod.body[0]) ntmp = deepcopy(item) ast.node.body.append(ntmp) item._name = "(*" + item._name + ")" st = nodes.Decl("vtable_" + ret.mname) st._ctype = nodes.ComposedType("vtable_" + ret.mname) st._ctype._specifier = 1 st._ctype._storage = 2 st._ctype.fields = private_func ast.node.body.append(st) parse = Declaration() cl = ret.mname vt = "vtable_" + cl free = "void delete() { void *fr = (void*)(self - sizeof(struct " + vt + ")); free(fr);}" d_free = parse.parse(free) m_free = mangle(d_free.body[0], cl, "CM") vlist[cl].append(m_free) free = "void delete(struct " + cl + " *self) { void *fr = (void*)( ((struct " + vt + " *)(self)) - 1); free(fr);}" d_free = parse.parse(free) d_free.body[0]._name = m_free["mangle"] ast.node.body.append(d_free.body[0]) tmp = deepcopy(d_free) tmp.body[0]._name = "(*" + tmp.body[0]._name + ")" tmp.body[0].body = None st._ctype.fields.append(tmp.body[0]) ptr_func = "" for item in vlist[cl]: ptr_func += "ptr->" + item["mangle"] + " = &" + item["mangle"] + ";" dl = "struct " + cl + " *alloc" code = vt + " *ptr = (struct " + vt + " *) malloc(sizeof(struct " + cl + ") + sizeof(struct " + vt + "));" \ + ptr_func + "return (struct " + cl + " *)(ptr + 1);" alloc = dl + "(){" + code + "}" d_alloc = parse.parse(alloc) m_alloc = mangle(d_alloc.body[0], cl, "C") clist[cl].append(m_alloc) ast.node.body.append(d_alloc.body[0]) dn = "struct " + cl + " *new" code = "struct " + cl + " *ptr = " + m_alloc["mangle"] + "(); return ptr;" new = dn + "(){" + code + "}" d_new = parse.parse(new) m_new = mangle(d_new.body[0], ret.mname, "C") clist[cl].append(m_new) ast.node.body.append(d_new.body[0]) return True
#!/usr/bin/python3 # -*- coding: utf-8 -*- import mangling import sys if not (len(sys.argv) is 2): print('./test.py "filename"') exit(1) from cnorm.parsing.declaration import Declaration from cnorm.passes import to_c cparse = Declaration() ast = cparse.parse_file(sys.argv[1]) for index, decl in enumerate(ast.body): cString = decl.to_c() print(cString, end='') print(decl) mangled = "" try: mangled = mangling.mangle(decl, mangling.OriginIsModule, 'DUMMY_MODUL_NAME')._name print(mangled) unmangled = mangling.unmangle(mangled) print(unmangled) print(unmangled.decl.to_c()) except Exception as e: print(str(e)) if index < len(ast.body) - 1: print('')
class ManglingTest: """Allow to check if the mangling is conform to the documentation""" cparse = Declaration() mangler = Mangler(mangle_qualifiers=True) unmangler = Unmangler() okString = '[\033[92mPASSED\033[0m]' failString = '[\033[91mFAILED\033[0m]' tests = {} def add_test(self, test_name, c_string, expected_mangling, origin, origin_name, expected_unmangling=None, context=[], is_virtual=False): """ Add a test to the pool :param test_name: name of the test, to pass to run member function :type test_name: string :param c_string: c declaration, including the ';' :type c_string: string :param expected_mangling: the mangling that should be producued from c_string :type expected_mangling: string :param origin: the origin of the c_string declaration :type origin: mangling.DECLARATION_FROM_[MODULE|INSTANCE|OBJECT] :param origin_name: the name of the class|module th declaration is from :type origin_name: string :param expected_unmangling: the c declaration to expect from demangling 'expected_mangling'. Usefull only if significantly different from c_string. :type expected_unmangling: string :param context: c declaration that from which c_string depend. :type context: string array :param is_virtual: specify if the expression should be considered virtual :type is_virtual: bool """ if test_name in self.tests: raise Exception('Test {} has already been added'.format(test_name)) self.tests[test_name] = { 'c_string': c_string, 'expected_mangling': expected_mangling, 'origin': origin, 'origin_name': origin_name, 'is_virtual': is_virtual, 'context': context } if expected_unmangling != None: self.tests[test_name]['expected_unmangling'] = expected_unmangling def run_all(self): """ Run all the test in the pool """ for test_name in self.tests.keys(): self.run(test_name) def run(self, test_name): """ Run a single test :param test_name: a test name already specified to add_test :type test_name: string """ if not (test_name in self.tests): raise Exception('Test {} does not exist'.format(test_name)) c_body = '' for context in self.tests[test_name]['context']: c_body += context c_body += self.tests[test_name]['c_string'] c_ast = '' origin_c_string = '' try: c_ast = self.cparse.parse(c_body) origin_c_string = c_ast.body[len( self.tests[test_name]['context'])].to_c() except Exception as e: self._print_assert_equal( test_name, '\n' + str(e), None, 'Parsing for \'' + test_name + '\' : [' + '{result}' + ']') return mangled = '' unmangled = '' try: decl = c_ast.body[len(self.tests[test_name]['context'])] mangled = self.mangler.mangle( decl._name, decl._ctype, self.tests[test_name]['origin'], self.tests[test_name]['origin_name'], virtual=self.tests[test_name]['is_virtual']) except Exception as e: self._print_assert_equal(test_name, e, None, 'Mangling for \'{name}\' : {result}') return try: unmangled = self.unmangler.unmangle(mangled).to_c() except Exception as e: self._print_assert_equal(test_name, e, None, 'Unmangling for \'{name}\' : {result}') return self._print_assert_equal(test_name, mangled, self.tests[test_name]['expected_mangling'], 'Mangling for \'{name}\' : {result}') if 'expected_unmangling' in self.tests[test_name]: self._print_assert_equal( test_name, str(unmangled).replace('\n', ''), self.tests[test_name]['expected_unmangling'], 'Unmangling for \'{name}\' : {result}') else: self._print_assert_equal(test_name, str(unmangled), str(origin_c_string), 'Unmangling for \'{name}\' : {result}') return def _print_assert_equal(self, test_name, arg1, arg2, format_string): """ print format_string and arg1 arg2, depnding of the result of arg1 == arg2 :param arg1: whatever you expect to be equal to arg2 :type arg1: whaterver you want :param arg2: whatever you expect to be equal to arg1 :type arg2: whaterver you want :param format_string: format_string to print, may expect the following key : 'result' :type format_string: string ready for format. Can include the 'result' key. """ # python format() cannot space pad align string @v@ print( format_string.format( name=test_name, result=(self.okString if arg1 == arg2 else self.failString))) if arg1 != arg2: print('\tExpecting : ' + (arg2 if isinstance(arg2, str) else repr(arg2))) print('\tHad : ' + (arg1 if isinstance(arg1, str) else repr(arg1)))
class UnittestModule(unittest.TestCase): def setUp(self): self.cparse = Declaration() self.kparse = KoocG() def tearDown(self): self.cparse = None self.kparse = None KoocFile.debugCleanAll() if hasattr(self, "res") and not hasattr(self.res, "to_c"): self.assertFalse(self.res.diagnostic.get_content()) ## SIMPLE TO MORE COMPLEX TEST OF VALIDS MODULES def test_empty_module(self): self.res = self.kparse.parse( """ @module Test { } """) self.assertEqual(str(self.res.to_c()), "") def test_declaration_variable(self): self.res = self.kparse.parse( """ @module Test { void test; } """) self.assertEqual(str(self.res.to_c()), "extern void M4Test__v4test;\n") def test_declaration_assignement_variable(self): self.res = self.kparse.parse( """ @module Test { int test = 42; } """) self.assertEqual(str(self.res.to_c()), "extern int M4Test__i4test;\n") def test_declaration_function_implicit_void(self): self.res = self.kparse.parse( """ @module Test { void test(); } """) self.assertEqual(str(self.res.to_c()), "extern void M4Test__v4testv();\n") def test_declaration_function_explicit_void(self): self.res = self.kparse.parse( """ @module Test { void test(void); } """) self.assertEqual(str(self.res.to_c()), "extern void M4Test__v4testv(void);\n") def test_declaration_function(self): self.res = self.kparse.parse( """ @module Test { char *test(int **toto, float tata[]); } """) self.assertEqual(str(self.res.to_c()), "extern char *M4Test__Pc4testPPiAf(int **toto, float tata[]);\n") def test_variable_overload(self): self.res = self.kparse.parse( """ @module Mayuri { int tuturu; float tuturu; } """) self.assertEqual(str(self.res.to_c()), "extern int M6Mayuri__i6tuturu;\nextern float M6Mayuri__f6tuturu;\n") def test_variable_and_function_with_no_param(self): self.res = self.kparse.parse( """ @module Mayuri { int tuturu; int tuturu(); } """) self.assertEqual(str(self.res.to_c()), "extern int M6Mayuri__i6tuturu;\nextern int M6Mayuri__i6tuturuv();\n") def test_function_return_value_overload(self): self.res = self.kparse.parse( """ @module Mayuri { int tuturu(float toto); float tuturu(float tutu); } """) self.assertEqual(str(self.res.to_c()), "extern int M6Mayuri__i6tuturuf(float toto);\n\ extern float M6Mayuri__f6tuturuf(float tutu);\n") def test_function_params_value_overload(self): self.res = self.kparse.parse( """ @module Mayuri { double **tuturu(char toto[], void* ptr[]); double** tuturu(int tutu); } """) self.assertEqual(str(self.res.to_c()), "extern double **M6Mayuri__PPd6tuturuAcAPv(char toto[], void *ptr[]);\n\ extern double **M6Mayuri__PPd6tuturui(int tutu);\n") ## TODO : TESTS WITH SOME FUNCTION POINTER ## TEST OF OVERLOADS WITH DIFFERENTS STORAGES, QUALIFIERS OR SPECIFIER def test_auto_variable(self): waited = self.cparse.parse(""" extern auto int M4Test__i4test; """) self.res = self.kparse.parse( """ @module Test { auto int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_register_variable(self): waited = self.cparse.parse(""" extern register int M4Test__i4test; """) self.res = self.kparse.parse( """ @module Test { register int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_typedef_variable(self): waited = self.cparse.parse(""" extern typedef int M4Test__i4test; """) self.res = self.kparse.parse( """ @module Test { typedef int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_static_variable(self): waited = self.cparse.parse(""" extern static int M4Test__i4test; """) self.res = self.kparse.parse( """ @module Test { static int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_extern_variable(self): waited = self.cparse.parse(""" extern extern int M4Test__i4test; """) self.res = self.kparse.parse( """ @module Test { extern int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_inline_variable(self): with self.assertRaises(KoocException) as cm: print(self.kparse.parse( """ @module Test { inline int test; } """)) # def test_virtual_variable(self): # waited = self.cparse.parse(""" # extern virtual int M4Test__i4test; # """) # self.res = self.kparse.parse( # """ # @module Test # { # virtual int test; # } # """) # self.assertEqual(str(self.res.to_c()), str(waited.to_c())) # def test_explicit_variable(self): # waited = self.cparse.parse(""" # extern explicit int M4Test__i4test; # """) # self.res = self.kparse.parse( # """ # @module Test # { # explicit int test; # } # """) # self.assertEqual(str(self.res.to_c()), str(waited.to_c())) # def test_forceinline_variable(self): # waited = self.cparse.parse(""" # extern forceinline int M4Test__i4test; # """) # self.res = self.kparse.parse( # """ # @module Test # { # forceinline int test; # } # """) # self.assertEqual(str(self.res.to_c()), str(waited.to_c())) # def test_thread_variable(self): # waited = self.cparse.parse(""" # extern thread int M4Test__i4test; # """) # self.res = self.kparse.parse( # """ # @module Test # { # thread int test; # } # """) # self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_volatile_variable(self): waited = self.cparse.parse(""" extern volatile int M4Test__V_i4test; """) self.res = self.kparse.parse( """ @module Test { volatile int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_restrict_variable(self): waited = self.cparse.parse(""" extern restrict int M4Test__R_i4test; """) self.res = self.kparse.parse( """ @module Test { restrict int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_long_variable(self): waited = self.cparse.parse(""" extern long int M4Test__li4test; """) self.res = self.kparse.parse( """ @module Test { long int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_long_long_variable(self): waited = self.cparse.parse(""" extern long long int M4Test__lli4test; """) self.res = self.kparse.parse( """ @module Test { long long int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_short_variable(self): waited = self.cparse.parse(""" extern short int M4Test__si4test; """) self.res = self.kparse.parse( """ @module Test { short int test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_const_ptr_variable(self): waited = self.cparse.parse(""" extern const int *M4Test__PC_i4test; """) self.res = self.kparse.parse( """ @module Test { int const* test; } """) self.assertEqual(str(self.res.to_c()), str(waited.to_c())) def test_complex_variable(self): self.res = self.kparse.parse( """ @module Test { auto unsigned int const* const* test; } """) waited = self.cparse.parse(""" extern auto unsigned int const* const* M4Test__PC_PC_Ui4test; """) self.assertEqual(str(self.res.to_c()), str(waited.to_c()))