Commits

Marko Tasic committed bad1f45

added initial files; broken compilation to c

Comments (0)

Files changed (11)

+from uco import *
+from stdio import printf
+
+def main(argc, argv):
+    '''
+    int main(int, char **);
+    '''
+    __args__(int, int, typeptr(typeptr(char)))
+    __vars__(s=int)
+    s = 0
+    return s
+from uco import *
+from stdio import printf
+
+def main(argc, argv):
+    '''
+    int main(int, char **);
+    '''
+    __args__(int, int, dtypeptr(char))
+    __vars__(i=int)
+    
+    for i in range(argc):
+        #~ printf('%s', args[i])
+        printf('%s', "aaa")
+    
+    return 0
+import os
+import sys
+import platform
+
+python_implementation = platform.python_implementation()
+
+if python_implementation in ('CPython', 'PyPy'):
+    from .emu import *
+else:
+    from .native import *

uco/emu/__init__.py

+from .uco import *
+from .compiler import *
+

uco/emu/compiler.py

+__all__ = ['Compiler']
+
+import os
+import sys
+import ast
+import logging
+import itertools
+from collections import OrderedDict as odict
+
+logging.basicConfig(
+    # format='%(asctime)s %(levelname)s %(funcName)s: %(message)s', 
+    # format='%(levelname)s %(message)s %(funcName)s', 
+    format='%(levelname)s %(message)s', 
+    level=logging.DEBUG,
+)
+
+'''
+module Python
+{
+    mod = Module(stmt* body)
+        | Interactive(stmt* body)
+        | Expression(expr body)
+
+        -- not really an actual node but useful in Jython's typesystem.
+        | Suite(stmt* body)
+
+    stmt = FunctionDef(identifier name, arguments args, 
+                           stmt* body, expr* decorator_list, expr? returns)
+          | ClassDef(identifier name, 
+             expr* bases,
+             keyword* keywords,
+             expr? starargs,
+             expr? kwargs,
+             stmt* body,
+             expr* decorator_list)
+          | Return(expr? value)
+
+          | Delete(expr* targets)
+          | Assign(expr* targets, expr value)
+          | AugAssign(expr target, operator op, expr value)
+
+          -- use 'orelse' because else is a keyword in target languages
+          | For(expr target, expr iter, stmt* body, stmt* orelse)
+          | While(expr test, stmt* body, stmt* orelse)
+          | If(expr test, stmt* body, stmt* orelse)
+          | With(withitem* items, stmt* body)
+
+          | Raise(expr? exc, expr? cause)
+          | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
+          | Assert(expr test, expr? msg)
+
+          | Import(alias* names)
+          | ImportFrom(identifier? module, alias* names, int? level)
+
+          | Global(identifier* names)
+          | Nonlocal(identifier* names)
+          | Expr(expr value)
+          | Pass | Break | Continue
+
+          -- XXX Jython will be different
+          -- col_offset is the byte offset in the utf8 string the parser uses
+          attributes (int lineno, int col_offset)
+
+          -- BoolOp() can use left & right?
+    expr = BoolOp(boolop op, expr* values)
+         | BinOp(expr left, operator op, expr right)
+         | UnaryOp(unaryop op, expr operand)
+         | Lambda(arguments args, expr body)
+         | IfExp(expr test, expr body, expr orelse)
+         | Dict(expr* keys, expr* values)
+         | Set(expr* elts)
+         | ListComp(expr elt, comprehension* generators)
+         | SetComp(expr elt, comprehension* generators)
+         | DictComp(expr key, expr value, comprehension* generators)
+         | GeneratorExp(expr elt, comprehension* generators)
+         -- the grammar constrains where yield expressions can occur
+         | Yield(expr? value)
+             | YieldFrom(expr? value)
+         -- need sequences for compare to distinguish between
+         -- x < 4 < 3 and (x < 4) < 3
+         | Compare(expr left, cmpop* ops, expr* comparators)
+         | Call(expr func, expr* args, keyword* keywords,
+             expr? starargs, expr? kwargs)
+         | Num(object n) -- a number as a PyObject.
+         | Str(string s) -- need to specify raw, unicode, etc?
+         | Bytes(bytes s)
+         | Ellipsis
+         -- other literals? bools?
+
+         -- the following expression can appear in assignment context
+         | Attribute(expr value, identifier attr, expr_context ctx)
+         | Subscript(expr value, slice slice, expr_context ctx)
+         | Starred(expr value, expr_context ctx)
+         | Name(identifier id, expr_context ctx)
+         | List(expr* elts, expr_context ctx) 
+         | Tuple(expr* elts, expr_context ctx)
+
+          -- col_offset is the byte offset in the utf8 string the parser uses
+          attributes (int lineno, int col_offset)
+
+    expr_context = Load | Store | Del | AugLoad | AugStore | Param
+
+    slice = Slice(expr? lower, expr? upper, expr? step) 
+          | ExtSlice(slice* dims) 
+          | Index(expr value) 
+
+    boolop = And | Or 
+
+    operator = Add | Sub | Mult | Div | Mod | Pow | LShift 
+                 | RShift | BitOr | BitXor | BitAnd | FloorDiv
+
+    unaryop = Invert | Not | UAdd | USub
+
+    cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
+
+    comprehension = (expr target, expr iter, expr* ifs)
+
+    excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
+                    attributes (int lineno, int col_offset)
+
+    arguments = (arg* args, identifier? vararg, expr? varargannotation,
+                     arg* kwonlyargs, identifier? kwarg,
+                     expr? kwargannotation, expr* defaults,
+                     expr* kw_defaults)
+    arg = (identifier arg, expr? annotation)
+
+    -- keyword arguments supplied to call
+    keyword = (identifier arg, expr value)
+
+    -- import name with optional 'as' alias.
+    alias = (identifier name, identifier? asname)
+
+    withitem = (expr context_expr, expr? optional_vars)
+}
+'''
+
+class NodeCompiler(ast.NodeVisitor):
+    def __init__(self, module_name, module_node):
+        ast.NodeVisitor.__init__(self)
+        self.name = module_name
+        self.node = module_node
+        self.defs = odict()
+        self.blocks = []
+    
+    def compile(self):
+        source = self.compile_Module(self.node)
+        return source
+    
+    def get_compile_func_name(self, node):
+        return 'compile_%s' % node.__class__.__name__
+    
+    def get_compile_func(self, node):
+        compile_func_name = self.get_compile_func_name(node)
+        compile_func = getattr(self, compile_func_name)
+        return compile_func
+    
+    def get_and_call_compile_func(self, node, *args, **kwargs):
+        compile_func = self.get_compile_func(node)
+        return compile_func(node, *args, **kwargs)
+    
+    def check_expect(self, expect, lcls):
+        if expect:
+            for key in expect:
+                if expect[key] != lcls[key]:
+                    raise SyntaxError('Not supported')
+    
+    def eval_ucosmos_call(self, func):
+        name, args, kwargs = func
+        
+        '''
+        if name == 'typeptr':
+            if len(args) != 1:
+                raise SyntaxError('Expected one argument')
+            
+            if kwargs:
+                raise SyntaxError('Not supported')
+            
+            t = args[0]
+            
+            if isinstance(t, bytes) or isinstance(t, str):
+                return '%s*' % t
+            elif isinstance(t, tuple) or isinstance(t, list):
+                return '%s*' % self.eval_ucosmos_call(t)
+        elif name == 'dtypeptr':
+            if len(args) != 1:
+                raise SyntaxError('Expected one argument')
+            
+            if kwargs:
+                raise SyntaxError('Not supported')
+            
+            t = args[0]
+            
+            if isinstance(t, bytes) or isinstance(t, str):
+                return '%s**' % t
+            elif isinstance(t, tuple) or isinstance(t, list):
+                return '%s**' % self.eval_ucosmos_call(t)
+        else:
+            return '%s(%s)' % (name, ', '.join(args))
+        '''
+        
+        return '%s(%s)' % (name, ', '.join([
+            arg if isinstance(arg, bytes) or isinstance(arg, str) else self.eval_ucosmos_call(arg)
+            for arg in args
+        ]))
+    
+    def eval_function_args(self, func_args):
+        args = []
+        
+        for n in func_args:
+            if isinstance(n, bytes) or isinstance(n, str):
+                args.append(n)
+            elif isinstance(n, tuple) or isinstance(n, list):
+                args.append(self.eval_ucosmos_call(n))
+        
+        return args
+    
+    def eval_function_vars(self, func_vars):
+        vars = []
+        
+        for a, t in func_vars:
+            if isinstance(t, bytes) or isinstance(t, str):
+                vars.append((a, t))
+            elif isinstance(t, tuple) or isinstance(t, list):
+                vars.append((a, self.eval_ucosmos_call(t)))
+        
+        return vars
+    
+    def compile_Module(self, node, expect=None, indent=0):
+        '''
+        Module(stmt* body)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        node_body = getattr(node, 'body', [])
+        
+        # check expected
+        self.check_expect(expect, locals())
+        
+        #
+        # compile
+        #
+        segs = []
+        self.blocks.append(node)
+        
+        for n in node_body:
+            seg = self.get_and_call_compile_func(n, indent=indent + 1)
+            segs.append(seg)
+        
+        source = '\n'.join(segs)
+        source += '\x00'
+        self.blocks.pop()
+        return source
+    
+    def compile_FunctionDef(self, node, expect=None, indent=0):
+        '''
+        FunctionDef(
+            identifier name,
+            arguments args, 
+            stmt* body,
+            expr* decorator_list,
+            expr? returns
+        )
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        node_name = node.name
+        node_args = node.args
+        node_body = getattr(node, 'body', [])
+        node_decorator_list = getattr(node, 'decorator_list', [])
+        node_returns = getattr(node, 'returns', None)
+        
+        name = node_name
+        _args, _kwargs = self.get_and_call_compile_func(node_args, indent=indent + 1)
+        
+        if _kwargs:
+            args = _args[:-len(_kwargs)]
+            kwargs = [(k, v) for k, v in zip(_args[-len(_kwargs):], _kwargs)]
+        else:
+            args = _args
+            kwargs = _kwargs
+        
+        # check expected
+        self.check_expect(expect, locals())
+        
+        #
+        # compile
+        #
+        segs = []
+        func_doc = None # ''' doc string '''
+        func_args = None # [('res', 'void'), ('', 'void')]
+        func_vars = None # []
+        func_body = []
+        
+        for n in node_body:
+            if isinstance(n, ast.Expr):
+                n_value = n.value
+                
+                if isinstance(n_value, ast.Bytes) or isinstance(n_value, ast.Str):
+                    func_doc = self.get_and_call_compile_func(n_value, indent=indent + 1)
+                    continue
+                elif isinstance(n_value, ast.Call):
+                    n_value_func = n_value.func
+                    n_value_func_id = n_value_func.id
+                    
+                    if n_value_func_id == '__args__':
+                        # ('__args__', ['int', 'int', ('typeptr', [('typeptr', ['char'], [])], [])], [])
+                        func_call = self.get_and_call_compile_func(n, indent=indent + 1)
+                        func_args = func_call[1]
+                        continue
+                    elif n_value_func_id == '__vars__':
+                        # ('__vars__', [], [('s', 'int')])
+                        func_call = self.get_and_call_compile_func(n, indent=indent + 1)
+                        func_vars = func_call[2]
+                        continue
+            
+            seg = self.get_and_call_compile_func(n, indent=indent + 1)
+            func_body.append(seg)
+        
+        # evaluate special ucosmos function calls in func_args and func_vars
+        #~ print('!!', _args, _kwargs)
+        #~ print('!!', args, kwargs)
+        #~ print('!!!', repr(func_doc), func_args, func_vars, func_body)
+        func_args = self.eval_function_args(func_args)
+        func_vars = self.eval_function_vars(func_vars)
+        #~ print('!!!', repr(func_doc), func_args, func_vars, func_body)
+        
+        # function definition
+        seg = '%s %s(%s) {' % (
+            func_args[0],
+            name,
+            ', '.join(
+                '%s %s' % (t, p) for t, p in zip(func_args[1:], args)
+            ),
+        )
+        segs.append(seg)
+        
+        # function variables
+        for a, t in func_vars:
+            seg = '%s %s;' % (t, a)
+            segs.append(seg)
+        
+        # function body declaration
+        seg = '\n'.join(func_body)
+        segs.append(seg)
+        
+        # end of function
+        seg = '}'
+        segs.append(seg)
+        
+        source = '\n'.join(segs)
+        return source
+    
+    def compile_ClassDef(self, node, expect=None, indent=0):
+        '''
+        ClassDef(
+            identifier name, 
+            expr* bases,
+            keyword* keywords,
+            expr? starargs,
+            expr? kwargs,
+            stmt* body,
+            expr* decorator_list
+        )
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Return(self, node, expect=None, indent=0):
+        '''
+        Return(expr? value)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        node_value = getattr(node, 'value', None)
+        value = self.get_and_call_compile_func(node_value, indent=indent + 1)
+        
+        # check expected
+        self.check_expect(expect, locals())
+        
+        source = 'return %s;' % value
+        return source
+    
+    def compile_Delete(self, node, expect=None, indent=0):
+        '''
+        Delete(expr* targets)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Assign(self, node, expect=None, indent=0):
+        '''
+        Assign(expr* targets, expr value)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        node_targets = getattr(node, 'targets', [])
+        node_value = node.value
+        
+        targets = [self.get_and_call_compile_func(n, indent=indent + 1) for n in node_targets]
+        value = self.get_and_call_compile_func(node_value, indent=indent + 1)
+        print('#', targets, value)
+        
+        # check expected
+        self.check_expect(expect, locals())
+        
+        # NOTE: prob need fix
+        if value is None:
+            values = ['NULL'];
+        elif isinstance(value, bool):
+            values = [value]
+        elif isinstance(value, int):
+            values = [value]
+        elif isinstance(value, float):
+            values = [value]
+        elif isinstance(value, bytes):
+            values = [value]
+        elif isinstance(value, str):
+            values = [value]
+        
+        segs = []
+        
+        for t, v in zip(targets, values):
+            segs.append('%s = %s;' % (t, v))
+        
+        source = '\n'.join(segs)
+        return source
+    
+    def compile_AugAssign(self, node, expect=None, indent=0):
+        '''
+        AugAssign(expr target, operator op, expr value)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_For(self, node, expect=None, indent=0):
+        '''
+        For(expr target, expr iter, stmt* body, stmt* orelse)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        node_target = node.target
+        node_iter = node.iter
+        node_body = getattr(node, 'body', [])
+        node_orelse = getattr(node, 'orelse', [])
+        
+        target = self.get_and_call_compile_func(node_target, indent=indent + 1)
+        iter = self.get_and_call_compile_func(node_iter, indent=indent + 1)
+        
+        body = [
+            self.get_and_call_compile_func(n, indent=indent + 1)
+            for n in node_body
+        ]
+        
+        orelse = [
+            self.get_and_call_compile_func(n, indent=indent + 1)
+            for n in node_orelse
+        ]
+        
+        # check expected
+        self.check_expect(expect, locals())
+        
+        segs = []
+        print('%', target, iter, body, orelse)
+        
+        if iter[0] == 'range':
+            seg = 'for (%s = 0; i < %s; i++) {' % (target, iter[1][0])
+            segs.append(seg)
+        
+            for n in body:
+                seg = '%s(%s)' % (
+                    n[0],
+                    ', '.join(n[1]),
+                )
+                segs.append(seg)
+            
+            seg = '}'
+            segs.append(seg)
+        else:
+            raise SyntaxError('Not supported')
+            
+        source = '\n'.join(segs)
+        return source
+    
+    def compile_While(self, node, expect=None, indent=0):
+        '''
+        While(expr test, stmt* body, stmt* orelse)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_If(self, node, expect=None, indent=0):
+        '''
+        If(expr test, stmt* body, stmt* orelse)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_With(self, node, expect=None, indent=0):
+        '''
+        With(withitem* items, stmt* body)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Raise(self, node, expect=None, indent=0):
+        '''
+        Raise(expr? exc, expr? cause)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Try(self, node, expect=None, indent=0):
+        '''
+        Try(
+            stmt* body,
+            excepthandler* handlers,
+            stmt* orelse,
+            stmt* finalbody
+        )
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Assert(self, node, expect=None, indent=0):
+        '''
+        Assert(expr test, expr? msg)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Import(self, node, expect=None, indent=0):
+        '''
+        Import(alias* names)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        raise SyntaxError('Not supported')
+    
+    def compile_ImportFrom(self, node, expect=None, indent=0):
+        '''
+        ImportFrom(identifier? module, alias* names, int? level)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        node_module = getattr(node, 'module', '')
+        node_names = getattr(node, 'names', [])
+        node_level = getattr(node, 'level', 0)
+        
+        module = node_module
+        path = node_module.replace('.', os.sep) + '.h'
+        names = [self.get_and_call_compile_func(n, indent=indent + 1) for n in node_names]
+        
+        # check expected
+        self.check_expect(expect, locals())
+        
+        #
+        # compile
+        #
+        segs = []
+        
+        # check if module exists localy or assume its global (system)
+        if os.path.exists(path) or module == 'uco':
+            seg = '#include "%s"' % path
+        else:
+            seg = '#include <%s>' % path
+        
+        seg += ' /* '
+        seg += ', '.join(names)
+        seg += ' */'
+        segs.append(seg)
+        
+        # final compile step
+        source = '\n'.join(segs)
+        return source
+    
+    def compile_Global(self, node, expect=None, indent=0):
+        '''
+        Global(identifier* names)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Nonlocal(self, node, expect=None, indent=0):
+        '''
+        Nonlocal(identifier* names)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Expr(self, node, expect=None, indent=0):
+        '''
+        Expr(expr value)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        value = node.value
+        source = self.get_and_call_compile_func(value, expect=expect, indent=indent + 1)
+        return source
+    
+    def compile_Pass(self, node, expect=None, indent=0):
+        '''
+        Pass
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ';'
+        return source
+    
+    def compile_Break(self, node, expect=None, indent=0):
+        '''
+        Break
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = 'break'
+        return source
+    
+    def compile_Continue(self, node, expect=None, indent=0):
+        '''
+        Continue
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = 'continue'
+        return source
+    
+    def compile_BoolOp(self, node, expect=None, indent=0):
+        '''
+        BoolOp(boolop op, expr* values)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_BinOp(self, node, expect=None, indent=0):
+        '''
+        BinOp(expr left, operator op, expr right)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_UnaryOp(self, node, expect=None, indent=0):
+        '''
+        UnaryOp(unaryop op, expr operand)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Lambda(self, node, expect=None, indent=0):
+        '''
+        Lambda(arguments args, expr body)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_IfExp(self, node, expect=None, indent=0):
+        '''
+        IfExp(expr test, expr body, expr orelse)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Dict(self, node, expect=None, indent=0):
+        '''
+        Dict(expr* keys, expr* values)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Set(self, node, expect=None, indent=0):
+        '''
+        Set(expr* elts)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_ListComp(self, node, expect=None, indent=0):
+        '''
+        ListComp(expr elt, comprehension* generators)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_SetComp(self, node, expect=None, indent=0):
+        '''
+        SetComp(expr elt, comprehension* generators)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_DictComp(self, node, expect=None, indent=0):
+        '''
+        DictComp(expr key, expr value, comprehension* generators)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_GeneratorExp(self, node, expect=None, indent=0):
+        '''
+        GeneratorExp(expr elt, comprehension* generators)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Yield(self, node, expect=None, indent=0):
+        '''
+        Yield(expr? value)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_YieldFrom(self, node, expect=None, indent=0):
+        '''
+        YieldFrom(expr? value)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Compare(self, node, expect=None, indent=0):
+        '''
+        Compare(expr left, cmpop* ops, expr* comparators)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Call(self, node, expect=None, indent=0):
+        '''
+        Call(
+            expr func,
+            expr* args,
+            keyword* keywords,
+            expr? starargs,
+            expr? kwargs
+        )
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        node_func = node.func
+        node_args = getattr(node, 'args', None)
+        node_keywords = getattr(node, 'keywords', None)
+        node_starargs = getattr(node, 'starargs', None)
+        node_kwargs = getattr(node, 'kwargs', None)
+        
+        #
+        # func
+        #
+        func_name = self.get_and_call_compile_func(node_func, indent=indent + 1)
+        args = [self.get_and_call_compile_func(n, indent=indent + 1) for n in node_args]
+        keywords = [self.get_and_call_compile_func(n, indent=indent + 1) for n in node_keywords]
+        
+        # check expected
+        self.check_expect(expect, locals())
+        
+        if node_starargs:
+            raise SyntaxError('Not supported')
+        
+        if node_kwargs:
+            raise SyntaxError('Not supported')
+        
+        return func_name, args, keywords
+        
+    def compile_Num(self, node, expect=None, indent=0):
+        '''
+        Num(object n) -- a number as a PyObject.
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        return node.n
+    
+    def compile_Str(self, node, expect=None, indent=0):
+        '''
+        Str(string s) -- need to specify raw, unicode, etc?
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        return node.s
+    
+    def compile_Bytes(self, node, expect=None, indent=0):
+        '''
+        Bytes(bytes s)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        return node.s
+    
+    def compile_Ellipsis(self, node, expect=None, indent=0):
+        '''
+        Ellipsis
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Attribute(self, node, expect=None, indent=0):
+        '''
+        Attribute(expr value, identifier attr, expr_context ctx)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Subscript(self, node, expect=None, indent=0):
+        '''
+        Subscript(expr value, slice slice, expr_context ctx)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Starred(self, node, expect=None, indent=0):
+        '''
+        Starred(expr value, expr_context ctx)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Name(self, node, expect=None, indent=0):
+        '''
+        Name(identifier id, expr_context ctx)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = node.id
+        return source
+    
+    def compile_List(self, node, expect=None, indent=0):
+        '''
+        List(expr* elts, expr_context ctx) 
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Tuple(self, node, expect=None, indent=0):
+        '''
+        Tuple(expr* elts, expr_context ctx)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Load(self, node, expect=None, indent=0):
+        '''
+        Load
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Store(self, node, expect=None, indent=0):
+        '''
+        Store
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Del(self, node, expect=None, indent=0):
+        '''
+        Del
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_AugLoad(self, node, expect=None, indent=0):
+        '''
+        AugLoad
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_AugStore(self, node, expect=None, indent=0):
+        '''
+        AugStore
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Param(self, node, expect=None, indent=0):
+        '''
+        Param
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Slice(self, node, expect=None, indent=0):
+        '''
+        Slice(expr? lower, expr? upper, expr? step)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_ExtSlice(self, node, expect=None, indent=0):
+        '''
+        ExtSlice(slice* dims)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Index(self, node, expect=None, indent=0):
+        '''
+        Index(expr value) 
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_And(self, node, expect=None, indent=0):
+        '''
+        And
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Or(self, node, expect=None, indent=0):
+        '''
+        Or
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Add(self, node, expect=None, indent=0):
+        '''
+        Add
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Sub(self, node, expect=None, indent=0):
+        '''
+        Sub
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Mult(self, node, expect=None, indent=0):
+        '''
+        Mult
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Div(self, node, expect=None, indent=0):
+        '''
+        Div
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Mod(self, node, expect=None, indent=0):
+        '''
+        Mod
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Pow(self, node, expect=None, indent=0):
+        '''
+        Pow
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_LShift(self, node, expect=None, indent=0):
+        '''
+        LShift
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_RShift(self, node, expect=None, indent=0):
+        '''
+        RShift
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_BitOr(self, node, expect=None, indent=0):
+        '''
+        BitOr
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_BitXor(self, node, expect=None, indent=0):
+        '''
+        BitXor
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_BitAnd(self, node, expect=None, indent=0):
+        '''
+        BitAnd
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_FloorDiv(self, node, expect=None, indent=0):
+        '''
+        FloorDiv
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Invert(self, node, expect=None, indent=0):
+        '''
+        Invert
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Not(self, node, expect=None, indent=0):
+        '''
+        Not
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_UAdd(self, node, expect=None, indent=0):
+        '''
+        UAdd
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_USub(self, node, expect=None, indent=0):
+        '''
+        USub
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Eq(self, node, expect=None, indent=0):
+        '''
+        Eq
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_NotEq(self, node, expect=None, indent=0):
+        '''
+        NotEq
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Lt(self, node, expect=None, indent=0):
+        '''
+        Lt
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_LtE(self, node, expect=None, indent=0):
+        '''
+        LtE
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Gt(self, node, expect=None, indent=0):
+        '''
+        Gt
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_GtE(self, node, expect=None, indent=0):
+        '''
+        GtE
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_Is(self, node, expect=None, indent=0):
+        '''
+        Is
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_IsNot(self, node, expect=None, indent=0):
+        '''
+        IsNot
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_In(self, node, expect=None, indent=0):
+        '''
+        In
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_NotIn(self, node, expect=None, indent=0):
+        '''
+        NotIn
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_comprehension(self, node, expect=None, indent=0):
+        '''
+        comprehension = (expr target, expr iter, expr* ifs)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_ExceptHandler(self, node, expect=None, indent=0):
+        '''
+        ExceptHandler(
+            expr? type,
+            identifier? name,
+            stmt* body
+        )
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        source = ''
+        return source
+    
+    def compile_arguments(self, node, expect=None, indent=0):
+        '''
+        arguments = (
+            arg* args,
+            identifier? vararg,
+            expr? varargannotation,
+            arg* kwonlyargs,
+            identifier? kwarg,
+            expr? kwargannotation,
+            expr* defaults,
+            expr* kw_defaults
+        )
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        args = getattr(node, 'args', [])
+        defaults = getattr(node, 'defaults', [])
+        
+        # check expected
+        self.check_expect(expect, locals())
+        
+        # NOTE: implement to accpet only allowed args and kwargs
+        args = [self.get_and_call_compile_func(n, indent=indent + 1) for n in args]
+        defaults = [self.get_and_call_compile_func(n, indent=indent + 1) for n in defaults]
+        return args, defaults
+    
+    def compile_arg(self, node, expect=None, indent=0):
+        '''
+        arg = (identifier arg, expr? annotation)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        arg = node.arg
+        annotation = getattr(node, 'annotation', None)
+        
+        # check expected
+        self.check_expect(expect, locals())
+        
+        # compile
+        source = arg
+        return arg
+    
+    def compile_keyword(self, node, expect=None, indent=0):
+        '''
+        keyword = (identifier arg, expr value)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        arg = getattr(node, 'arg', None)
+        value = getattr(node, 'value', None)
+        
+        # check expected
+        self.check_expect(expect, locals())
+        
+        #
+        # compile
+        #
+        kw_value = self.get_and_call_compile_func(value, indent=indent + 1)
+        return arg, kw_value
+    
+    def compile_alias(self, node, expect=None, indent=0):
+        '''
+        alias = (identifier name, identifier? asname)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        name = getattr(node, 'name', None)
+        identifier = getattr(node, 'identifier', None)
+        
+        # check expected
+        self.check_expect(expect, locals())
+        
+        #
+        # compile
+        #
+        # NOTE: check correctnes, and whats used for identifier
+        source = name
+        return source
+    
+    def compile_withitem(self, node, expect=None, indent=0):
+        '''
+        withitem = (expr context_expr, expr? optional_vars)
+        '''
+        logging.debug('%s%s', ' ' * indent if indent else '', node.__class__.__name__)
+        raise SyntaxError('Not supported')
+
+class Compiler(object):
+    def __init__(self, filename):
+        self._filename = filename
+    
+    def compile(self):
+        with open(self._filename, 'rb') as f:
+            source = f.read()
+        
+        module_ast = ast.parse(source, self._filename)
+        module_name = os.path.splitext(os.path.basename(self._filename))[0]
+        
+        node_compiler = NodeCompiler(module_name, module_ast)
+        c_source = node_compiler.compile()
+        return c_source
+
+if __name__ == '__main__':
+    compiler = Compiler(filename=sys.argv[1])
+    source = compiler.compile()
+    print('compile C source:', source, sep='\n')
+
+def printf(fmt, *args):
+    print(fmt % args, sep='', end='')
+__all__ = ['TCC']
+
+import os
+import sys
+
+from ctypes import *
+from ctypes.util import find_library
+
+from .compiler import Compiler
+
+libtcc = CDLL(find_library('tcc'))
+
+TCC_OUTPUT_MEMORY = c_int(0)
+
+class TCCState(Structure):
+    pass
+
+class TCCError(Exception):
+    pass
+
+libtcc.tcc_new.restype = POINTER(TCCState)
+libtcc.tcc_new.argtypes = None
+
+libtcc.tcc_set_output_type.restype = c_int
+libtcc.tcc_set_output_type.argtypes = [POINTER(TCCState), c_int]
+
+libtcc.tcc_add_include_path.restype = c_int
+libtcc.tcc_add_include_path.argtypes = [POINTER(TCCState), c_char_p]
+
+libtcc.tcc_compile_string.restype = c_int
+libtcc.tcc_compile_string.argtypes = [POINTER(TCCState), c_char_p]
+
+libtcc.tcc_get_symbol.restype = c_void_p
+libtcc.tcc_get_symbol.argtypes = [POINTER(TCCState), c_char_p]
+
+c_main_cft = CFUNCTYPE(c_int, c_int, POINTER(c_char_p))
+
+class TCC(object):
+    def __init__(self):
+        self._state = libtcc.tcc_new()
+        
+        if not self._state:
+            raise TCCError('Could not create tcc state')
+    
+    def compile_string(self, source):
+        if isinstance(source, str):
+            source = source.encode()
+        
+        self._c_source = create_string_buffer(source)
+        libtcc.tcc_set_output_type(self._state, TCC_OUTPUT_MEMORY)
+        libtcc.tcc_add_include_path(self._state, c_char_p(b'uco'))
+        
+        if libtcc.tcc_compile_string(self._state, self._c_source) == -1:
+            raise TCCError('Could not compile')
+        
+        self._size = libtcc.tcc_relocate(self._state, None)
+        self._mem = create_string_buffer(self._size)
+        self._size = libtcc.tcc_relocate(self._state, self._mem)
+        
+    def get_symbol(self, symbol):
+        if isinstance(symbol, str):
+            symbol = symbol.encode()
+        
+        c_symbol = create_string_buffer(symbol)
+        c_res = libtcc.tcc_get_symbol(self._state, c_symbol)
+        return c_res
+
+def compile_and_run(args):
+    compiler = Compiler(args[0])
+    source = compiler.compile()
+    print('compile C source:', source, sep='\n')
+    
+    tcc = TCC()
+    tcc.compile_string(source)
+    
+    c_main_symbol = tcc.get_symbol('main')
+    c_main = cast(c_main_symbol, c_main_cft)
+    c_argc = c_int(len(args))
+    c_argv_t = c_char_p * len(args)
+    c_argv_a = c_argv_t()
+    
+    for i, arg in enumerate(args):
+        c_argv_a[i] = c_char_p(
+            arg.encode() if isinstance(arg, str) else arg
+        )
+    
+    c_argv = cast(c_argv_a, POINTER(c_char_p))
+    c_res = c_main(c_argc, c_argv)
+    return c_res
+
+if __name__ == '__main__':
+    res = compile_and_run(sys.argv[1:])
+    sys.exit(res)
+import builtins as _py_builtins
+import types as _py_types
+
+from .stdio import *
+
+# function / method arguments types
+def __args__(*args, **kwargs):
+    '''
+    '''
+
+# function / method local variables types
+def __vars__(*args, **kwargs):
+    '''
+    '''
+
+# struct / union fields types
+def fields(*args, **kwargs):
+    '''
+    '''
+
+#
+# void, null, bool, int, float, char, wchar
+#
+class primitive(object):
+    '''
+    '''
+
+#
+# struct, union, enum
+#
+class composite(object):
+    '''
+    '''
+
+#
+# tuple, list, set, dict
+#
+class abstract(object):
+    '''
+    '''
+
+#
+# pointers, types, arrays
+#
+def addressof(obj):
+    return id(obj)
+
+class ptr(_py_builtins.int, primitive):
+    '''
+    ptr(obj) -> ptr
+    '''
+    def __new__(cls, obj):
+        self = super().__new__(cls, id(obj))
+        return self
+
+class typeptr(primitive):
+    def __init__(self, type):
+        self._type = type
+    
+    def __call__(self, obj):
+        return ptr(obj)
+
+class dtypeptr(primitive):
+    def __init__(self, type):
+        self._type = type
+    
+    def __call__(self, obj):
+        return ptr(ptr(obj))
+
+class array(primitive):
+    def __init__(self, type, len):
+        self._type = type
+        self._len = len
+
+#
+# void
+#
+class void(primitive):
+    '''
+    void() -> void
+    '''
+
+#
+# null
+#
+class null(primitive):
+    '''
+    null() -> NoneType
+    '''
+    def __new__(cls):
+        return None
+
+#
+# bool
+#
+class bool(primitive):
+    '''
+    bool(value : bool) -> bool
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.bool):
+            raise TypeError('wrong type')
+        
+        return _py_builtins.bool(value)
+
+#
+# int
+#
+class int(_py_builtins.int, primitive):
+    '''
+    int(value : int) -> int
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.int):
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self
+
+class int8(_py_builtins.int, primitive):
+    '''
+    int8(value : int) -> int8
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.int):
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self
+
+class int16(_py_builtins.int, primitive):
+    '''
+    int16(value : int) -> int16
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.int):
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self
+
+class int32(_py_builtins.int, primitive):
+    '''
+    int32(value : int) -> int32
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.int):
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self
+
+class int64(_py_builtins.int, primitive):
+    '''
+    int64(value : int) -> int64
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.int):
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self
+
+class uint(_py_builtins.int, primitive):
+    '''
+    uint(value : int) -> uint
+    '''
+
+class uint8(_py_builtins.int, primitive):
+    '''
+    uint8(value : int) -> uint8
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.int):
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self
+
+class uint16(_py_builtins.int, primitive):
+    '''
+    uint16(value : int) -> uint16
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.int):
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self
+
+class uint32(_py_builtins.int, primitive):
+    '''
+    uint32(value : int) -> uint32
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.int):
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self
+
+class uint64(_py_builtins.int, primitive):
+    '''
+    uint64(value : int) -> uint64
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.int):
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self
+
+#
+# float
+#
+class float(_py_builtins.float, primitive):
+    '''
+    float(value : float) -> float
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.float):
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self
+
+class double(_py_builtins.float, primitive):
+    '''
+    double(value : float) -> double
+    '''
+    def __new__(cls, value):
+        if not isinstance(value, _py_builtins.float):
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self
+
+#
+# char
+#
+class char(_py_builtins.str, primitive):
+    '''
+    char(value : int) -> char
+    char(value : char) -> char
+    '''
+    def __new__(self, value):
+        if isinstance(value, int):
+            value = chr(value)
+        elif isinstance(value, char):
+            value = value
+        elif isinstance(value, _py_builtins.str) and len(value) == 1:
+            value = value[0]
+        elif isinstance(value, _py_builtins.bytes) and len(value) == 1:
+            value = chr(value[0])
+        else:
+            raise TypeError('wrong type')
+        
+        self = super().__new__(cls, value)
+        return self

uco/native/__init__.py

+
+#include "uco.h"
+
+#define dtypeptr(type) type**
+#define typeptr(type) type*