Beispiel #1
0
def aliasParser(parser, name, decl, generic):
    parser.nextToken()

    typ = False
    while not Parser.isEnd(parser):
        if parser.thisToken().token != "\n" and parser.thisToken().type != "indent":
            if typ:
                Error.parseError(parser, "Unexpected token " + parser.thisToken().token)
            typ = Types.parseType(parser)
        parser.nextToken()

    if decl:
        alias = parser.interfaces[parser.package][name]

        tmp = Types.Alias(parser.package, name, typ, generic)
        alias.name = tmp.name
        alias.normalName = tmp.normalName
        alias.typ = tmp.typ
        alias.generic = tmp.generic
        alias.remainingGen = tmp.remainingGen
        alias.types = tmp.types
        alias.methods = tmp.methods
    if decl:
        parser.interfaces[parser.package][name] = alias

    Scope.decrScope(parser)
Beispiel #2
0
def createParser(parser,
                 name="",
                 typ=None,
                 check=True,
                 imutable=True,
                 attachTyp=False):  # : creation
    if name == "":
        name = parser.lookBehind()

    if name.type != "identifier":
        Error.parseError(
            parser, "variable name must be of type identifier, not " +
            parser.lookBehind().type)

    name = name.token

    if name[0].lower() != name[0]:
        Error.parseError(parser, "variable name must be lower case")

    node = Tree.Create(name, Types.Null(), parser)
    node.package = parser.package
    node.imutable = imutable

    if attachTyp:
        node.attachTyp = attachTyp

    parser.currentNode.addNode(node)

    node.varType = typ
    if check and typ is None:
        parser.nextToken()
        typ = Types.parseType(parser)

        node.varType = typ
Beispiel #3
0
def enumParser(parser, name, decl, generic):
    const = parser.interfaces[parser.package][name].const
    existing_generics = parser.interfaces[parser.package][name].generic
    existing_generics.update(generic)

    #const = coll.OrderedDict()
    enum = Types.Enum(parser.package, name, const, existing_generics)

    if decl:
        parser.interfaces[parser.package][name] = enum
    """if parser.lookInfront().token == "\n":
        parser.nextToken()
        Parser.callToken(parser)
        parser.nextToken()"" \
    """

    while not Parser.isEnd(parser):
        t = parser.nextToken()

        if t.token == "\n" or t.type == "indent":
            Parser.callToken(parser)
            continue

        if t.type != "identifier":
            Error.parseError(parser, "expecting identifier")

        varName = t.token

        if varName[0].upper() != varName[0]:
            Error.parseError(parser, "constructor type must be capitalized")

        args = []
        nextT = parser.nextToken()
        #print(varName)
        #print(nextT)
        if nextT.token == "(":
            args = Types.parseType(parser).list

        const[varName] = args

        if decl:
            Scope.addVar(Tree.PlaceHolder(parser),
                         parser,
                         varName,
                         Scope.Type(
                             True,
                             Types.FuncPointer(args, enum, generic=generic)
                             if len(args) > 0 else enum),
                         _global=True)

        t = parser.thisToken()
        if t.token == "\n" or t.type == "indent":
            Parser.callToken(parser)

    parser.currentNode.addNode(Tree.Enum(const, name, parser, generic))

    Scope.decrScope(parser)
Beispiel #4
0
def sizeofParser(parser):
    parser.nextToken()

    s = Tree.Sizeof(parser)
    typ = Types.parseType(parser)

    s.typ = typ
    s.type = Types.I32(unsigned= True)
    parser.currentNode.addNode(s)
Beispiel #5
0
 def loop(n):
     if type(n) in [Tree.PlaceHolder, Tree.Place]:
         return B
     elif type(n) is Tree.Field:
         inner = loop(n.nodes[0])
         return Types.Interface(False, {n.field: inner})
     elif type(n) is Tree.ArrRead:
         inner = loop(n.nodes[0])
         return Types.Array(False, inner)
     else:
         n.error("unexpected token " + n.token.token)
Beispiel #6
0
def parseJson(parser):
    parse = Tree.Decoder(parser)
    parser.currentNode.addNode(parse)
    parser.currentNode = parse

    parser.nextToken()

    typ = Types.parseType(parser)

    parse.type = Types.FuncPointer([Types.All], typ)
    parse.shouldBeTyp = typ

    parser.currentNode = parse.owner
Beispiel #7
0
def createParser(parser, name= "", typ= None, check= True, imutable= True, attachTyp= False): # : creation
    if name == "":
        name = parser.lookBehind()

    if name.type != "identifier":
        Error.parseError(parser, "variable name must be of type identifier, not "+parser.lookBehind().type)

    name = name.token

    if name[0].lower() != name[0]:
        Error.parseError(parser, "variable name must be lower case")

    node = Tree.Create(name, Types.Null(), parser)
    node.package = parser.package
    node.imutable = imutable

    if attachTyp:
        node.attachTyp = attachTyp

    parser.currentNode.addNode(node)

    node.varType = typ
    if check and typ is None:
        parser.nextToken()
        typ = Types.parseType(parser)

        node.varType = typ
def simplifyArrRead(operator, iter, parser):
    readMethodName = callMethodCode(operator.nodes[0], "op_get", operator.nodes[0].type, parser, False)
    readMethodName.type.args[1] = operator.nodes[1].type
    readMethodName.type.returnType = operator.type
    # if operator.nodes[0].type.isType(Types.Pointer):
    #    readMethodName.replaced = operator.nodes[0].type.pType.remainingGen
    # else:
    #    readMethodName.replaced = operator.nodes[0].type.remainingGen

    deref = Tree.Operator("*", operator)
    deref.unary = True
    deref.type = operator.type
    deref.owner = operator.owner

    func = Tree.FuncCall(operator)
    func.type = Types.Pointer(operator.type)
    func.addNode(readMethodName)

    func.addNode(operator.nodes[0])
    func.addNode(operator.nodes[1])

    deref.addNode(func)

    operator.owner.nodes[iter] = deref

    return deref
Beispiel #9
0
def generics(parser, fname):
    generic = coll.OrderedDict()

    while parser.thisToken().token != "]":
        name = parser.nextToken().token

        typ = Types.T(name, Types.All, parser.package+"."+fname)
        if parser.thisToken().type != "identifier":
            Error.parseError(parser, "type name must be an identifier")

        if not parser.nextToken().token in [":", ",", "]"]:
            Error.parseError(parser, "expecting ,")

        if parser.thisToken().token == ":":
            parser.nextToken()
            typ = Types.T(name, Types.parseType(parser), parser.package+"."+fname)

            if parser.lookInfront().token != "]":
                parser.nextToken()

        Scope.addVar(Tree.PlaceHolder(parser), parser, name, Scope.Type(False, typ))
        generic[name] = typ

        if parser.lookInfront().token == "]":
            parser.nextToken()
            break

    parser.nextToken()
    return generic
Beispiel #10
0
def genericT(parser):
    parser.nextToken()
    if len(parser.currentNode.nodes) > 0:
        func = parser.currentNode.nodes.pop()
    else:
        Error.parseError(parser, "unexpected ::")

    generic = Tree.Generic(parser)
    parser.currentNode.addNode(generic)
    generic.addNode(func)

    generic.generic = []

    if parser.thisToken().token != "[":
        Error.parseError(parser, "expecting [")

    parser.nextToken()

    while parser.thisToken().token != "]":
        if parser.thisToken().token == ",":
            parser.nextToken()
            parser.nodeBookmark[-1] = len(parser.currentNode.nodes)
            continue

        generic.generic.append(Types.parseType(parser))
        t = parser.thisToken().token
        parser.nextToken()
Beispiel #11
0
def genericT(parser):
    parser.nextToken()
    if len(parser.currentNode.nodes) > 0:
        func = parser.currentNode.nodes.pop()
    else:
        Error.parseError(parser, "unexpected ::")

    generic = Tree.Generic(parser)
    parser.currentNode.addNode(generic)
    generic.addNode(func)

    generic.generic = []

    if parser.thisToken().token != "[":
        Error.parseError(parser, "expecting [")

    parser.nextToken()

    while parser.thisToken().token != "]":
        if parser.thisToken().token == ",":
            parser.nextToken()
            parser.nodeBookmark[-1] = len(parser.currentNode.nodes)
            continue

        generic.generic.append(Types.parseType(parser))
        t = parser.thisToken().token
        parser.nextToken()
Beispiel #12
0
    def toCHelp(self, tree=None, isGlobal=True):
        if tree is None:
            tree = self.tree

        self.incrDeferred()

        includes = Types.TmpCodegen()

        for (iter, i) in enumerate(tree):
            if type(i) is Tree.CreateAssign and i.extern and i.nodes[0].name == "_":
                i.compileToC(includes)

        for (iter, i) in enumerate(tree):
            if type(i) is Tree.FuncStart:
                funcStart = i
                funcBrace = i.owner.nodes[iter+1]
                funcBody = i.owner.nodes[iter+2]
                Func.forwardRef(funcStart, funcBrace, funcBody, self)

        for i in tree:
            if type(i) in [Tree.Type, Tree.Enum] or (type(i) is Tree.CreateAssign and i.extern and i.nodes[0].name == "_"): continue
            i.compileToC(self)
            self.addSemicolon(i)

        self.decrDeferred()

        return "".join(includes.out_parts)
Beispiel #13
0
    def compileToC(self, codegen):
        self.typ.toCType()

        #if self.typ.package == "_global" and type(self.typ) in [Types.Struct, Types.Enum]:
        #    codegen.append("NULL")
        #    return

        package = self.typ.package if self.typ.package != "" else "_global"
        fullName = SimplifyAst.toUniqueID(package, self.typ.normalName, self.typ.remainingGen)

        if not type(self.typ) in [Types.Interface, Types.Pointer, Types.Alias, Types.Null]:
            if type(self.typ) is Types.T:
                typeof_none = Typeof(self, Types.Null())
                Tree.castFrom(typeof_none.type, Parser.IType, typeof_none, "", codegen)
            else:
                codegen.append(f"{fullName}_get_type(NULL," + codegen.getContext() + ")")
        else:
            if type(self.typ) is Types.Pointer:
                codegen.append("_global_boxPointerType(_global_PointerTypeInit(")
                tmp = Typeof(self, self.typ.pType)
                Cast.castFrom(tmp.type, Parser.IType, tmp, "", codegen)
                codegen.append(",0)," + codegen.getContext() + ")")
            elif type(self.typ) is Types.Null:
                codegen.append(f"&None_Type")
            else:
                codegen.append(f"&{fullName}_Type")
Beispiel #14
0
def index(parser, unary=False):

    if not unary:
        unary = ExprParser.isUnary(parser, parser.lookBehind())


    if not unary and len(parser.currentNode.nodes) == 0:
        Error.parseError(parser, "unexpected .")

    field = parser.nextToken()

    if not field.type in ["identifier", "i32"]:
        Error.parseError(parser, "field name must be an identifier")

    acess = Tree.Field(0, Types.Null(), parser)
    acess.unary = unary
    acess.number = field.type == "i32"

    field = field.token

    acess.owner = parser.currentNode
    acess.field = field

    if not unary:
        acess.addNode(parser.currentNode.nodes[-1])
        parser.currentNode.nodes[-1] = acess
    else:
        parser.currentNode.addNode(acess)
Beispiel #15
0
def generics(parser, fname):
    generic = coll.OrderedDict()

    while parser.thisToken().token != "]":
        name = parser.nextToken().token

        typ = Types.T(
            name, Types.All, parser.package + "." +
            fname if parser.package != "_global" else fname)
        if parser.thisToken().type != "identifier":
            Error.parseError(parser, "type name must be an identifier")

        if not parser.nextToken().token in [":", ",", "]"]:
            Error.parseError(parser, "expecting ,")

        Scope.addVar(Tree.PlaceHolder(parser), parser, name,
                     Scope.Type(False, typ))

        if parser.thisToken().token == ":":
            parser.nextToken()
            interface = Types.parseType(parser)

            if not type(interface) in [
                    Types.Interface, Types.EnumT, Types.Assign
            ]:
                Error.parseError(
                    parser, "Type variable " + name +
                    ", must either be a interface or enumT, not " +
                    str(interface))

            typ.fromObj(
                Types.T(
                    name, interface, parser.package + "." +
                    fname if parser.package != "_global" else fname))

            if parser.lookInfront().token != "]":
                parser.nextToken()

        generic[typ.name] = typ

        if parser.lookInfront().token == "]":
            parser.nextToken()
            break

    parser.nextToken()
    return generic
Beispiel #16
0
def createAndAssignParser(parser, imutable= True): # let i assignment
    node = parser.currentNode

    parser.nextToken() #get current token to position of =

    checkIt = False
    attachTyp = False

    if parser.lookInfront().token == ".":

        attachTyp = Types.parseType(parser, attachTyp= True)
        parser.nextToken()
        if not imutable or not type(node) is Tree.Root:
            Error.parseError(parser, "expecting =, not .")
        parser.nextToken()


    name = parser.thisToken()

    typ = None

    if parser.nextToken().token == ":":
        checkIt = True

        parser.nextToken()
        typ = Types.parseType(parser)

        parser.nextToken()
    elif parser.thisToken().token != "=":
        Error.parseError(parser, "expecting =, not"+parser.thisToken().token)

    n = Tree.CreateAssign(parser)

    parser.currentNode.addNode(n)
    parser.currentNode = n

    createParser(parser, name= name, typ= typ, check= checkIt, imutable= imutable, attachTyp= attachTyp)

    if attachTyp:
        assignParser(parser, name=attachTyp.name+"_"+name.token, package= attachTyp.package, init=True)
    else:
        assignParser(parser, name= name.token, init= True)

    parser.currentNode = node
Beispiel #17
0
def asOperator(parser):
    lastToken = parser.lookBehind()

    if not isUnary(parser, lastToken):
        op = Tree.Operator("as", parser)
        parser.nextToken()
        op.type = Types.parseType(parser)
        Parser.Opcode(parser, "as", lambda: operatorPop(parser, op, 1, unary=True))
    else:
        Error.parseError(parser, "unexpected as operator ")
Beispiel #18
0
def castParser(parser):
    if len(parser.currentNode.nodes) == 0:
        Error.parseError(parser, "Unexpected cast")

    parser.nextToken()

    node = Tree.CastToType(parser)
    node.type = Types.parseType(parser)
    node.addNode(parser.currentNode.nodes[-1])
    parser.currentNode.nodes[-1] = node
    node.owner = parser.currentNode
Beispiel #19
0
    def __init__(self):
        self.nodes = []
        self.type = Types.Null()
        self.names = []
        self.global_target = "full"

        self.name = ""
        self.inline = False
        self.called = 0
        self.perCall = 0

        self.before = []
Beispiel #20
0
    def loop(node):
        for iter in range(len(node.nodes)):
            i = node.nodes[iter]

            if not i.isEnd():
                loop(i)

            if type(i) is Tree.FuncCall and i.inline and i.type != Types.Null(
            ):
                if len(i.nodes) == 2:
                    node.nodes[iter] = i.nodes[1]
                    node.nodes[iter].owner = node
Beispiel #21
0
def typeOfVar(node, parser, package, name):
    if name in parser.imports: return Types.Package()
    if package == parser.package:
        for i in parser.scope["_global"]:
            if name in i:
                return i[name].type

    for i in parser.scope[package]:
        try:
            return i[name].type
        except: pass
    node.error("variable "+name+" does not exist")
Beispiel #22
0
 def loop(node):
     for i in node:
         if type(i) is Tree.If and i.type != Types.Null():
             for n in i.nodes[::2]:
                 if len(n.nodes) != 1: break
             else:
                 if not i.isEnd():
                     loop(i)
                 continue
             i.ternary = True
         if not i.isEnd():
             loop(i)
Beispiel #23
0
def offsetof(parser):
    parser.nextToken()

    s = Tree.Offsetof(parser)
    typ = Types.parseType(parser)
    if parser.nextToken().token != ",":
        Error.parseError(parser, "Expecting comma")

    field = parser.nextToken()
    if field.type != "identifier":
        Error.parseError(parser, "Expecting identifier, not " + field.type)

    if not field.token in typ.types:
        Error.parseError(parser, str(typ) + " does not have the field " + field.token)

    if type(typ) is Types.Array and typ.both and field.token == "length":
        Error.parseError(parser, "Cannot get offsetof parameter length on static array")

    s.typ = typ
    s.field = field.token
    s.type = Types.I32(unsigned=True)
    parser.currentNode.addNode(s)
                def bind():
                    if type(i.owner) is Tree.FuncCall and i.owner.nodes[0] == i: return
                    typ = type(i.type)

                    if typ is Types.FuncPointer:
                        if not type(i.nodes[0].type) in [Types.Struct]:
                            bind = Tree.ArrBind(i.field, self.nodes[0], self)
                            bind.type = i.type
                        else:
                            bind = Tree.Bind(r, self.nodes[0], self)
                            bind.type = Types.FuncPointer(self.type.args[1:], self.type.returnType, generic= self.type.generic, do= self.type.do)
                        self.owner.nodes[count] = bind
                        bind.owner = self.owner
Beispiel #25
0
def aliasParser(parser, name, decl, generic):
    parser.nextToken()

    typ = False
    while not Parser.isEnd(parser):
        if parser.thisToken().token != "\n" and parser.thisToken(
        ).type != "indent":
            if typ:
                Error.parseError(
                    parser, "Unexpected token " + parser.thisToken().token)
            typ = Types.parseType(parser)
        parser.nextToken()

    alias = Types.Alias(parser.package, name, typ, generic)

    if decl:
        del parser.structs[parser.package][
            name]  # = Struct.Struct(name, args, fields, coll.OrderedDict())

        parser.interfaces[parser.package][name] = alias

    Scope.decrScope(parser)
Beispiel #26
0
def traitParser(parser, name, decl, generic):
    interface = parser.interfaces[parser.package][name]
    meth = {}

    while not Parser.isEnd(parser):
        parser.nextToken()

        t = parser.thisToken()

        if t.token == "def":
            currentNode = parser.currentNode
            p = PlaceHolder(parser)
            parser.currentNode = p

            (methodName, names, types, brace, returnType,
             do) = FuncParser.funcHead(parser,
                                       decl,
                                       dontAdd=True,
                                       interfaceMethod=True)
            Scope.decrScope(parser)
            if methodName in meth:
                Error.parseError(parser,
                                 "Method " + methodName + ", already defined")
            meth[methodName] = brace.ftype
            parser.currentNode = currentNode
            parser.nextToken()
        else:
            Parser.declareOnly(parser, noVar=True)
            if len(parser.currentNode.nodes) > 0 and type(
                    parser.currentNode.nodes[0]) is Tree.Create:
                Error.parseError(
                    parser,
                    "Interfaces are abstract interfaces which is why only methods are supported"
                )

    names = {i.name: i.varType for i in parser.currentNode}
    #args = [i.varType for i in parser.currentNode]
    #fields = parser.currentNode.nodes

    if decl:
        i = interface.fromObj(
            Types.Interface(False,
                            names,
                            generic,
                            parser.package + "." +
                            name if parser.package != "_global" else name,
                            methods=meth))
        parser.interfaces[parser.package][name] = i

    Scope.decrScope(parser)
Beispiel #27
0
def addMethod(node, parser, attachTyp, name, func, otherNode=False):
    if type(attachTyp) is Types.Struct:
        parser.structs[attachTyp.package][attachTyp.normalName].addMethod(
            parser, name, func)
    elif type(attachTyp) is Struct.Struct:
        if type(func) is Types.FuncPointer:
            if len(func.args) == 0:
                node.error(
                    "the function attached must have a first parameter with type "
                    + attachTyp.package + "." + attachTyp.name)

            Types.Struct(False, attachTyp.name, attachTyp.types,
                         attachTyp.package,
                         attachTyp.generic).duckType(parser, func.args[0],
                                                     node, otherNode, 0)

        attachTyp.addMethod(parser, name, func)
    else:
        node.error("Can't add method to " + str(attachTyp))
Beispiel #28
0
def ifBody(parser):
    cond = Tree.IfCondition(parser)

    parser.currentNode.addNode(cond)
    parser.currentNode = cond

    single = 0

    parser.nodeBookmark.append(0)

    then = False
    while not (Parser.isEnd(parser) and then) :
        token = parser.nextToken()

        if token.token == "then" and not then:
            then = True
            ExprParser.endExpr(parser)

            parser.nodeBookmark.pop()

            block = Tree.Block(parser)
            cond.owner.addNode(block)
            parser.currentNode = block
            continue

        isEnd = Parser.maybeEnd(parser)

        if (token.token in ["else", "elif"]) and isEnd:
            break

        token = parser.thisToken()

        Parser.callToken(parser)

        next = parser.lookInfront()
        if (next.token == "else" or next.token == "elif") and isEnd:
            break

    ExprParser.endExpr(parser)

    cond.type = Types.Bool()

    parser.currentNode = cond.owner.owner
Beispiel #29
0
def traitParser(parser, name, decl, generic):
    meth = {}
    while not Parser.isEnd(parser):
        parser.nextToken()

        t = parser.thisToken()

        Parser.declareOnly(parser, noVar=True)

    names = {i.name: i.varType for i in parser.currentNode}
    args = [i.varType for i in parser.currentNode]
    fields = parser.currentNode.nodes

    if decl:
        del parser.structs[parser.package][name]# = Struct.Struct(name, args, fields, coll.OrderedDict())

        i = Types.Interface(False, names, generic, parser.package+"."+name)
        parser.interfaces[parser.package][name] = i

    Scope.decrScope(parser)
Beispiel #30
0
def isUseless(i):
    if i.repl:
        return

    if type(i) in [Tree.ReadVar, Tree.ArrRead]:
        i.error("useless read")
    elif type(i) in [Tree.Int, Tree.Array, Tree.ArrRead, Tree.String, Tree.Bool, Tree.Float]:
        i.error("useless literal")
    elif type(i) is Tree.Operator and not i.kind == "<-":
        i.error("useless operator")
    elif type(i) is Tree.FuncCall and not i.nodes[0].type.do:
        if i.type != Types.Null():
            i.error("not using return of function")
    try:
        t = i.curry
        if t: i.error("useless curry")
        t = i.partial
        if t: i.error("useless function application")
    except AttributeError:
        pass
Beispiel #31
0
def buildContext(parser):
    from TopCompiler import Parser

    contextType = parser.contextType
    # build context data type
    context = "_global_context"
    typesGeneratedByContext = ""

    from TopCompiler import Parser
    from TopCompiler import topc

    if type(Parser.IType) is Parser.TmpType:
        topc.global_parser.setTypeIntrospection()

    Parser.PointerType.toCType()

    types = {}
    for field in contextType:
        t = contextType[field]
        if t.package in parser.structs:
            types[field] = t.toCType()

    string = []
    (typesGen, mainC) = Types.getGeneratedDataTypes("_context")

    parser.typesInContext = list(Types.genericTypes.keys())

    Types.compiledTypes = coll.OrderedDict()
    Types.dataTypes = []

    string.append(typesGen)

    string.append("struct _global_Context {\n")
    for field in contextType:
        string.append(f"{types[field]} {field};")
    string.append("};\n")

    string.append(f"struct _global_Context {context};")

    return ("".join(string), mainC)
Beispiel #32
0
def callMethodCode(node, name, typ, parser, unary):
    isMethod = False
    if type(typ) is Types.Pointer and type(typ.pType) is Types.Alias:
        method = typ.pType.typ.hasMethod(parser, name, isP=True)
        if method:
            typ = typ.pType.typ
            isMethod = True

    elif type(typ) is Types.Alias:
        method = typ.typ.hasMethod(parser, name, isP= isMethod)
        if method:
            typ = typ.typ

    if not node.type.isType(Types.Pointer):
        name += "ByValue"


    length = 1 if unary else 2

    if type(typ) is Types.Pointer:
        typ = typ.pType

    package = "_global" if typ.package == "" else typ.package

    var = Tree.ReadVar(typ.normalName + "_" + name, True, node)
    var.package = package
    var.type = Types.FuncPointer([node.type] * length, node.type)

    while True:
        if typ.isType(Types.Pointer):
            typ = typ.pType
        else:
            break

    #if type(typ) in [Types.Struct, Types.Alias, Types.Enum]:
    var.replaced = typ.remainingGen

    return var
Beispiel #33
0
    def compile(self, opt):
        self.contexts = ["(&_global_context)"]

        self.parser.package = self.filename
        self.parser.imports = self.parser.allImports[self.filename]
        PostProcessing.simplifyAst(self.parser, self.tree)

        includes = self.toCHelp()

        mainCode = ""


        mainCode += ("".join(self.main_parts))
        outerCode = "".join(self.out_parts)
        forward_ref = "".join(self.header_parts)

        (generatedTypes, mainC) = Types.getGeneratedDataTypes(self.filename)
        Types.compiledTypes = coll.OrderedDict()
        Types.dataTypes = []

        mainC = "".join(self.init_types) + "\n" + mainC

        headerCode = f"{generatedTypes}\n{forward_ref}"
        print_code = "printf(" + '"' + self.filename + '\\n");'
        cCode = f"{outerCode}\nvoid {self.filename}InitTypes() {{ \n {mainC} }}\nvoid {self.filename}Init() {{ \n{mainCode};\n}};"

        #print("To C took :", time() - t)

        f = open("lib/" + self.filename + ".c", mode="w")
        f.write(cCode)
        f.close()

        f = open("lib/" + self.filename + ".h", mode="w")
        f.write(headerCode)
        f.close()

        return includes
Beispiel #34
0
    def loop(node, pos= 0):
        deleted = 0
        for iter in range(len(node.nodes)):

            iter -= deleted
            i = node.nodes[iter]

            if not i.isEnd():
                loop(i, iter)

            if type(i) is Tree.Else and len(i.owner.nodes) == 2:
                if i.owner.ternary:
                    i.owner.owner.nodes[pos] = i.owner.nodes[1].nodes[0]
                else:
                    i.owner.owner.nodes[pos] = i.owner.nodes[1]
                    i.owner.owner.nodes[pos].noBrackets = True

                i.owner.owner.nodes[pos].owner = i.owner.owner


            if type(i) is Tree.IfCondition:
                if isConstant(i.nodes[0]):
                    t = evaluate(i.nodes[0])
                    if (i.owner.ternary or i.owner.type == Types.Null()):
                        if t:
                            if i.owner.ternary:
                                i.owner.owner.nodes[pos] = i.owner.nodes[1].nodes[0]
                            else:
                                i.owner.owner.nodes[pos] = i.owner.nodes[1]
                                i.owner.owner.nodes[pos].noBrackets = True

                            i.owner.owner.nodes[pos].owner = i.owner.owner
                        else:
                            del i.owner.nodes[0]
                            del i.owner.nodes[0]
                            deleted += 2
    def loop(n, always=copy.deepcopy(tree)):
        count = 0
        for i in n:
            if type(i) is Tree.FuncStart:
                if not type(n) is Tree.Root:
                    Scope.addVar(i, parser, i.name, Scope.Type(True, i.ftype))
                Scope.incrScope(parser)

            elif type(i) in [Tree.If, Tree.While]:
                Scope.incrScope(parser)

            if not i.isEnd():
                loop(i)

            if type(i) is Tree.CreateAssign:
                if i.nodes[0].varType is None and i.nodes[0].name != "_":
                    i.nodes[0].varType = i.nodes[1].nodes[0].type

                    if i.nodes[0].attachTyp:
                        MethodParser.addMethod(
                            i, parser, i.nodes[0].attachTyp, i.nodes[0].name, i.nodes[1].nodes[0].type
                        )
                        i.nodes[0].isGlobal = True
                    else:
                        Scope.addVar(
                            i, parser, i.nodes[0].name, Scope.Type(i.nodes[0].imutable, i.nodes[1].nodes[0].type)
                        )
                        i.nodes[0].isGlobal = Scope.isGlobal(parser, i.nodes[0].package, i.nodes[0].name)
            elif type(i) is Tree.FuncBody:
                Scope.decrScope(parser)

                def check(n):
                    for c in n:
                        if type(c) is Tree.FuncCall:
                            if c.nodes[0].type.do and not i.do:
                                c.nodes[0].error("cannot call function with side effects in a pure function")

                        if not c.isEnd():
                            check(c)

                check(i)

            elif type(i) is Tree.Create:
                if not i.varType is None:
                    Scope.addVar(i, parser, i.name, Scope.Type(i.imutable, i.varType))
                    i.isGlobal = Scope.isGlobal(parser, i.package, i.name)

            elif type(i) is Tree.ReadVar:
                if i.name in parser.imports:
                    if not type(i.owner) is Tree.Field:
                        i.error("expecting .")
                elif type(i.type) is Tree.Type:
                    i.error("unexpected type " + str(i.type))

                i.type = Scope.typeOfVar(i, parser, i.package, i.name)
                self = i
                self.imutable = not Scope.isMutable(parser, self.package, self.name)
                self.isGlobal = Scope.isGlobal(parser, self.package, self.name)
                self.package = Scope.packageOfVar(parser, parser.package, self.name)
            elif type(i) is Tree.Field:

                def bind():
                    if type(i.owner) is Tree.FuncCall and i.owner.nodes[0] == i:
                        return
                    typ = type(i.type)

                    if typ is Types.FuncPointer:
                        if not type(i.nodes[0].type) in [Types.Struct]:
                            bind = Tree.ArrBind(i.field, self.nodes[0], self)
                            bind.type = i.type
                        else:
                            bind = Tree.Bind(r, self.nodes[0], self)
                            bind.type = Types.FuncPointer(self.type.args[1:], self.type.returnType)
                        self.owner.nodes[count] = bind
                        bind.owner = self.owner

                typ = i.nodes[0].type
                t = i.nodes[0]

                if type(typ) is Types.Package:
                    i.indexPackage = True
                    i.type = Scope.typeOfVar(i, parser, i.nodes[0].name, i.field)

                    i.nodes[0].package = i.nodes[0].name
                    i.nodes[0].name = ""
                else:
                    if type(typ) is Types.FuncPointer:
                        i.error("type " + str(typ) + " has no field " + i.field)

                    struct = typ

                    self = i
                    try:
                        i.type = struct.types[self.field]

                        if type(i.nodes[0].type) is Types.Array:
                            bind()
                    except KeyError:
                        method = struct.hasMethod(parser, self.field)

                        if not method:
                            self.error("type " + str(typ) + " has no field " + self.field)

                        self.type = method

                        r = Tree.ReadVar(typ.normalName + "_" + self.field, self.type, self)
                        r.type = self.type
                        r.package = typ.package if not typ.package == "_global" else ""
                        r.owner = self.owner

                        if type(i.owner) is Tree.FuncCall and i.owner.nodes[0] == i:
                            self.owner.nodes[0] = r
                            self.owner.nodes.insert(1, self.nodes[0])
                            count += 1
                        else:
                            bind()

            elif type(i) is Tree.Operator:
                if i.kind == "|>":
                    self = i

                    if len(self.nodes) != 2:
                        self.error("chain operator cannot be curried")

                    a = self.nodes[0].type
                    b = self.nodes[1].type

                    if not type(a) is Types.FuncPointer:
                        self.nodes[0].error("function chain operator works on functions only")
                    if not type(b) is Types.FuncPointer:
                        self.nodes[1].error("function chain operator works on functions only")

                    if len(b.args) == 0:
                        self.nodes[1].error("function must take atleast one argument")
                    if [a.returnType] != b.args:
                        self.nodes[1].error(
                            "function arguments don't match returnType of piped function: "
                            + str(a.returnType)
                            + " and "
                            + ", ".join([str(i) for i in b.args])
                        )

                    self.type = Types.FuncPointer(a.args, b.returnType)

                elif i.kind == "concat":
                    stringable = Types.Interface(False, {"toString": Types.FuncPointer([], Types.String(0))})
                    for c in i:
                        stringable.duckType(parser, c.type, Tree.PlaceHolder(c), c, 0)
                    i.type = Types.String(0)
                    i.partial = False
                    i.curry = False
                else:
                    if len(i.nodes) == 0:
                        import collections as coll

                        if i.kind in ["not", "or", "and"]:
                            T = Types.Bool()
                            gen = []
                        else:
                            T = Types.T("T", Types.All, "Operator")
                            gen = [("T", Types.All)]
                        i.type = Types.FuncPointer([T, T], T, coll.OrderedDict(gen))

                        if i.kind != "not":
                            i.unary = False
                    else:
                        partial = False
                        if type(i.nodes[0]) is Tree.Under:
                            partial = True
                            startType = False
                        else:
                            startType = i.nodes[0].type
                            if i.kind in ["not", "and", "or"]:
                                if startType != Types.Bool():
                                    i.nodes[0].error("logical operator " + i.kind + " only works on boolean")

                        for c in i.nodes[1:]:
                            if type(c) is Tree.Under:
                                partial = True
                            else:
                                if not partial and c.type != startType:
                                    c.error("Type mismatch " + str(startType) + " and " + str(c.type))
                                startType = c.type

                        i.partial = partial
                        typ = startType
                        if i.kind in ["==", "!=", "not", "and", "or", "<", ">", "<=", ">="]:
                            typ = Types.Bool()

                        if i.curry or i.partial:
                            normal = (1 if i.unary else 2) - len(i.nodes)
                            for c in i.nodes:
                                if type(c) is Tree.Under:
                                    normal += 1

                            if not startType:
                                import collections as coll

                                if i.kind in ["not", "or", "and"]:
                                    T = Types.Bool()
                                    gen = []
                                else:
                                    T = Types.T("t", Types.All, "Operator")
                                    gen = [("t", Types.All)]
                                typ = Types.FuncPointer([T, T], T, coll.OrderedDict(gen))

                                if normal == (1 if i.unary else 2):
                                    i.partial = False
                                    i.curry = True
                                    i.nodes = []
                            else:
                                typ = Types.FuncPointer([startType] * normal, typ)

                        i.type = typ
                        i.opT = startType

            elif type(i) is Tree.FuncCall:
                partial = False

                if not type(i.nodes[0].type) is Types.FuncPointer:
                    i.nodes[0].error("type " + str(i.nodes[0].type) + " is not callable")

                args = i.nodes[0].type.args
                newArgs = []

                if len(args) < len(i.nodes) - 1:
                    c = str(len(i.nodes) - 1 - len(args))
                    i.nodes[-1].error(("1 argument" if c == "1" else c + " arguments") + " too many")

                generics = {}
                for iter in range(len(i.nodes[1:])):
                    if type(i.nodes[iter + 1]) is Tree.Under:
                        partial = True
                        newArgs.append(iter)
                    else:
                        normalTyp = args[iter]
                        myNode = i.nodes[iter + 1]
                        normalNode = i

                        if Types.isGeneric(normalTyp):
                            normalTyp = resolveGen(normalTyp, myNode.type, generics, parser)

                        normalTyp.duckType(parser, myNode.type, i, myNode, iter + 1)

                newArgs = [Types.replaceT(args[c], generics) for c in newArgs]

                if len(args) > len(i.nodes) - 1:
                    i.curry = True
                    i.type = Types.FuncPointer(
                        [Types.replaceT(c, generics) for c in args[: len(args) - len(i.nodes) - 1]],
                        Types.replaceT(i.nodes[0].type.returnType, generics),
                    )
                elif not partial:
                    i.type = Types.replaceT(i.nodes[0].type.returnType, generics)
                else:
                    i.partial = True
                    i.type = Types.FuncPointer(newArgs, Types.replaceT(i.nodes[0].type.returnType, generics))
            elif type(i) is Tree.If:
                ElseExpr.checkIf(parser, i)
            elif type(i) is Tree.Block:
                i.type = i.nodes[-1].type if len(i.nodes) > 0 else Types.Null()
            elif type(i) is Tree.Assign:
                if not (type(i.owner) is Tree.CreateAssign and i.owner.nodes[0].varType is None):
                    normalNode = i.owner.nodes[0] if i.init else i.nodes[1]
                    normalTyp = i.owner.nodes[0].varType if i.init else i.nodes[0].type
                    myNode = i.nodes[0] if i.init else i.nodes[1]

                    normalTyp.duckType(parser, myNode.type, normalNode, myNode, (0 if i.init else 1))

            elif type(i) is Tree.Tuple:
                if len(i.nodes) == 0:
                    i.error("unexpected )")
                i.type = i.nodes[0].type
            elif type(i) is Tree.Array:
                arr = i

                if len(i.nodes) > 0:
                    if arr.init or arr.range:
                        if arr.nodes[0].type != Types.I32():
                            arr.nodes[0].error("expecting integer for range start, not " + str(arr.nodes[1].type))

                        if arr.range:
                            if arr.nodes[1].type != Types.I32():
                                arr.nodes[1].error("expecting integer for range end, not " + str(arr.nodes[1].type))
                            typ = Types.I32()
                        else:
                            typ = arr.nodes[1].type

                    else:
                        typ = arr.nodes[0].type
                        if typ == Types.Null():
                            arr.error("array elements must be non none")

                        for c in arr.nodes[1:]:
                            if typ != c.type:
                                c.error("type mismatch " + str(typ) + " and " + str(c.type))

                    arr.type = Types.Array(arr.mutable, typ)
            elif type(i) is Tree.InitPack:
                parser.imports.append(i.package)
            elif type(i) is Tree.InitStruct:
                s = i.s
                name = s.name
                args = s.fieldType

                if len(args) < len(i.nodes):
                    c = str(len(i.nodes) - 1 - len(args))
                    i.nodes[-1].error(("1 argument" if c == "1" else c + " arguments") + " too many")

                gen = {}
                for iter in range(len(i.nodes)):
                    normalTyp = args[iter]
                    myNode = i.nodes[iter]
                    normalNode = i

                    if Types.isGeneric(normalTyp):
                        normalTyp = resolveGen(normalTyp, myNode.type, gen)

                    normalTyp.duckType(parser, myNode.type, i, myNode, iter)

                i.type = Types.Struct(i.mutable, name, s.types, i.package, gen)

            elif type(i) is Tree.ArrRead:
                if not type(i.nodes[0].type) is Types.Array:
                    i.nodes[0].error("Type " + str(i.nodes[0].type) + "is not indexable")
                arrRead = i
                if len(arrRead.nodes) != 2 or not arrRead.nodes[1].type == Types.I32():
                    i.nodes[1].error("expecting single integer index")

                arrRead.type = arrRead.nodes[0].type.elemT
            elif type(i) is Tree.Generic:
                if not Types.isGeneric(i.nodes[0].type):
                    i.nodes[0].error("expecting generic type")

                gen = i.nodes[0].type.generic

                if len(gen) > len(i.generic):
                    i.error("missing " + str(len(gen) - len(i.generic)) + " generic parameters")
                elif len(gen) < len(i.generic):
                    i.error(str(len(i.generic) - len(gen)) + " too many generic parameters")

                v = list(gen.keys())
                replace = {v[index]: c for index, c in enumerate(i.generic)}

                for index, c in enumerate(gen):
                    gen[c].duckType(parser, i.generic[index], i.nodes[0], i, 0)

                i.type = Types.replaceT(i.nodes[0].type, replace)

                i.nodes[0].type.duckType(parser, i.type, i, i.nodes[0])

            if type(i) in [Tree.If, Tree.While]:
                Scope.decrScope(parser)

            count += 1
Beispiel #36
0
def funcHead(parser, decl= False, dontAdd= False, method= False, attachTyp = False):
    Scope.incrScope(parser)

    if parser.tokens[parser.iter+2].token == ".":
        if attachTyp: Error.parseError(parser, "unexpected .")
        parser.nextToken()
        name = parser.thisToken().token
        parser.nextToken()

        try:
            attachTyp = Types.Struct(False, name, parser.structs[parser.package][name].types, parser.package, {})
        except KeyError:
            Error.parseError(parser, "no attachable data structure found, called "+name)
        return funcHead(parser, decl, dontAdd, True, attachTyp)
    name = parser.nextToken()

    if name.type != "identifier":
        Error.parseError(parser, "function name must be of type identifier, not "+name.type)
    parser.nextToken()

    name = name.token

    g = {}
    if parser.thisToken().token != "(":
        if parser.thisToken().token == "[":
            g = generics(parser, (str(attachTyp)+"." if method else "")+name)
            if parser.thisToken().token == ".":
                if attachTyp: Error.parseError(parser, "unexpected .")
                if not Scope.varExists(parser, parser.package, name): Error.parseError(parser,
                     "cannot attach method to unknown type main."+name)

                try:
                    attachTyp = Types.Struct(False, name, parser.structs[parser.package][name].types, parser.package,
                                         parserMethodGen(parser, g, parser.structs[parser.package][name]))
                except KeyError:
                    Error.parseError(parser, "no attachable data structure found, called " + name)

                return funcHead(parser, decl, dontAdd, True, attachTyp)


        if parser.thisToken().token != "(":
            Error.parseError(parser, "expecting (")

    header = Tree.FuncStart(name, Types.Null(), parser)
    header.package = parser.package
    parser.currentNode.addNode(header)

    brace = Tree.FuncBraceOpen(parser)
    brace.name = name
    brace.package = parser.package

    parser.currentNode.addNode(brace)

    parser.currentNode = brace

    if method:
        if not type(parser.currentNode.owner) is Tree.Root and not decl:
            Error.parseError(parser, "method extension must be in out-most scope")

        typ = attachTyp
        self = parser.nextToken()
        if self.type != "identifier": Error.parseError(parser, "binding name must be identifier not "+self.type)
        self = self.token

        selfNode = Tree.Create(self, typ, parser)
        selfNode.package = parser.package
        selfNode.imutable = True

        parser.currentNode.addNode(selfNode)

        if not parser.lookInfront().token in [")", ","]:
            Error.parseError(parser, "expecting comma not "+parser.thisToken().token)


    if name[0].lower() != name[0]:
        Error.parseError(parser, "function name must be lower case")

    returnType = Types.Null()

    parser.paren += 1
    parser.nextToken()

    while parser.paren != parser.parenBookmark[-1] :
        b = parser.thisToken().token
        if b == ",":
            parser.nextToken()
            continue
        elif b == ")":
            parser.paren -= 1
            parser.nextToken()
            continue
        elif b == "(":
            Error.parseError(parser, "unexpected (")
        Parser.declareOnly(parser)
        parser.nextToken()

    t = parser.thisToken()
    do = False

    if t.token != "=" and t.token != "do":
        returnType = Types.parseType(parser)

        t = parser.nextToken()
        if t.token != "=" and t.token != "do":
            Error.parseError(parser, "expecting = or do")

    if t.token == "do":
        do = True

    parser.currentNode = brace.owner

    names = [i.name for i in brace.nodes]
    types = [i.varType for i in brace.nodes]

    func = Types.FuncPointer(
        types,
        returnType,
        g,
        do
    )

    if method:
        Scope.decrScope(parser)

        header.method = True
        header.types = types[1:]
        header.attachTyp = attachTyp
        header.normalName = name
        header.name = attachTyp.normalName+"_"+header.normalName

        MethodParser.checkIfOperator(parser, attachTyp, name, func)

        if decl:
            MethodParser.addMethod(brace, parser, attachTyp, name, func)

        return attachTyp.normalName+"_"+name, names, types, header, returnType, do

    parser.func[parser.package][name] = func

    header.ftype = Types.FuncPointer(types, returnType, g)
    if decl:
        if not dontAdd:
            Scope.addFunc(header, parser, name, Types.FuncPointer(types, returnType, g, do))

    return name, names, types, header, returnType, do