Example #1
0
def funcBody(parser, name, names, types, header, returnType, do):
    body = Tree.FuncBody(parser)
    body.name = name
    body.returnType = returnType
    body.package = parser.package
    body.do = do

    parser.currentNode.addNode(body)
    parser.currentNode = body

    for i in range(len(names)):
        n = Tree.InitArg(names[i], body)
        n.package = parser.package
        n.varType = types[i]
        n.imutable = not Scope.isMutable(parser, parser.package, names[i])
        body.addNode(n)

    parser.nextToken()
    Parser.callToken(parser) #incase next case is newline

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

    ExprParser.endExpr(parser)

    parser.currentNode = body.owner

    Scope.decrScope(parser)
Example #2
0
                    def recur(typ, pattern):
                        if type(pattern) is Tree.Tuple:
                            if len(pattern) > len(typ.list):
                                diff = len(pattern) - len(typ.list)
                                node.error(diff + " too few values to unpack")
                            elif len(pattern) < len(typ.list):
                                diff = len(typ.list) - len(pattern)
                                node.error(diff + " too many values to unpack")

                            for (index, p) in enumerate(pattern):
                                recur(typ.list[index], p)
                        elif type(pattern) is Tree.InitStruct:
                            for p in pattern:
                                if type(p) is Tree.Assign:
                                    name = p.nodes[0].name
                                    p = p.nodes[1]
                                else:
                                    name = p.name

                                if not name in typ.types:
                                    node.error("Object has no field " + name)
                                recur(typ.types[name], p)
                        else:
                            Scope.addVar(
                                node, parser, pattern.name,
                                Scope.Type(True, typ, i.global_target))
                            pattern.isGlobal = Scope.isGlobal(
                                parser, parser.package, pattern.name)
Example #3
0
def packDec(parser, name, pack= False):
    import os
    parser.opackage = name
    parser.package = os.path.basename(name)

    if pack:
        Scope.addPackage(parser, name)
Example #4
0
    def getName(token, nameOfVar=""):
        if nameOfVar == "":
            nameOfVar = token.token
        package = parser.package

        if nameOfVar in parser.structs[name]:
            if decl:
                if stage and nameOfVar in parser.structs[package]:
                    Error.parseError(parser,
                                     nameOfVar + " is already a struct")
                parser.structs[package][nameOfVar] = parser.structs[name][
                    nameOfVar]
            else:
                pass
                #Scope.addVar(place, parser, nameOfVar, parser.scope[name][0][nameOfVar])

            names.append((nameOfVar, "full"))
        elif nameOfVar in parser.interfaces[name]:
            if not decl: return

            if stage and nameOfVar in parser.interfaces[package]:
                Error.parseError(parser,
                                 nameOfVar + " is already an interface")
            parser.interfaces[package][nameOfVar] = parser.interfaces[name][
                nameOfVar]
        elif not decl and nameOfVar in parser.scope[name][0]:
            #can't set lambda
            Scope.addVar(place, parser, nameOfVar,
                         parser.scope[name][0][nameOfVar])
            names.append((nameOfVar, parser.scope[name][0][nameOfVar].target))
        elif not decl:
            Error.parseError(
                parser, "Package " + name +
                " does not have a variable, or type called " + nameOfVar)
Example #5
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)
Example #6
0
def funcBody(parser, name, names, types, brace, returnType, do):
    body = Tree.FuncBody(parser)
    body.name = name
    body.returnType = returnType
    body.package = parser.package
    body.do = do

    brace.body = body

    parser.currentNode.addNode(body)
    parser.currentNode = body

    for i in range(len(names)):
        n = Tree.InitArg(names[i], body)
        n.package = parser.package
        n.varType = types[i]
        n.imutable = not Scope.isMutable(parser, parser.package, names[i])
        body.addNode(n)

    parser.nextToken()
    Parser.callToken(parser)  #incase next case is newline

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

    ExprParser.endExpr(parser)

    parser.currentNode = body.owner

    Scope.decrScope(parser)
    return body
def packDec(parser, name, pack=False):
    import os
    parser.opackage = name
    parser.package = os.path.basename(name)

    if pack:
        Scope.addPackage(parser, name)
Example #8
0
def parserMethodGen(parser, gen, struct):
    sgen = struct.generic

    if len(gen) > len(sgen):
        Error.parseError(
            parser,
            str(len(gen) - len(sgen)) + " generic arguments too many")
    elif len(gen) < len(sgen):
        Error.parseError(
            parser,
            str(len(gen) - len(sgen)) + " generic arguments too few")

    newGen = coll.OrderedDict()
    for a, b in zip(gen, sgen):
        typ = sgen[b]

        aStripped = a[a.rfind(".") + 1:]

        if not a in sgen:
            Error.parseError(
                parser,
                "Unknown type parameter " + aStripped + " in " + str(struct))
        if gen[a].type != Types.All:
            typ = gen[
                b]  #@cleanup check if interface is compatible with structs regular generics  Error.parseError(parser, "unexpected :")
        newGen[a] = typ
        Scope.changeType(parser, aStripped, typ)

    return newGen
Example #9
0
    def validate(self, parser):
        checkUseless(self)

        actReturnType = Types.Null()

        if type(self.returnType) is str:
            Scope.decrScope(parser)
            return

        if self.returnType == Types.Null(): pass
        elif len(self.nodes) > 0:
            if self.nodes[-1].type == Types.Null():
                actReturnType = Types.Null()

            else:
                actReturnType = self.nodes[-1].type

        returnType = self.returnType
        name = self.name

        import AST as Tree

        try:
            returnType.duckType(
                parser, actReturnType, self,
                self.nodes[-1] if len(self.nodes) > 0 else Tree.Under(self), 0)
        except EOFError as e:
            Error.beforeError(e, "Return Type: ")

        if self.do:
            transform(self)

        Scope.decrScope(parser)
Example #10
0
    def validate(self, parser):
        node = self
        package = self.package

        if type(self.owner) is Tree.InitStruct:
            return

        if self.init:
            if type(self.name) is Tree.Tuple:
                for i in self.name:
                    if type(i) is Tree.ReadVar:
                        self.isGlobal = Scope.isGlobal(parser, self.package, i.name)
                        break
            else:
                self.isGlobal = Scope.isGlobal(parser, self.package, self.name)
            createTyp = self.createTyp
        else:
            varNode = self.nodes[0]
            canMutate(self.nodes[0])

        if len(node.nodes) == 0:
           self.error( "expecting expression")
        if self.init:
            if len(node.nodes) > 1:
                self.error( "expecting single expression, not multiple")

            typ = node.nodes[0].type
        else:
            if len(node.nodes) > 2:
                self.error("expecting single expression, not multiple")
            typ = node.nodes[1].type

        if typ == Types.Null() and not (self.init and type(self.nodes[0]) is Tree.Under):
            self.nodes[0].error("cannot assign nothing")
Example #11
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
Example #12
0
def typeParser(parser, decl= False):
    name = parser.nextToken()

    Scope.incrScope(parser)


    if name.type != "identifier":
        Error.parseError(parser, "type name must be an identifier")
    name = name.token

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

    import collections as coll
    gen = coll.OrderedDict()

    if parser.nextToken().token == "[":
        gen = FuncParser.generics(parser, name)

    if parser.thisToken().token != "=":
        if parser.thisToken().token == "with":
            tmp = parser.currentNode
            parser.currentNode = Tree.PlaceHolder(parser)
            Interface.traitParser(parser, name, decl, gen)
            parser.currentNode = tmp
            return

        Error.parseError(parser, "expecting =")
    tmp = parser.currentNode

    typ = Tree.Type(parser.package, name, parser)
    typ.package = parser.package
    typ.normalName = name

    tmp.addNode(typ)

    parser.currentNode = typ

    while not Parser.isEnd(parser):
        parser.nextToken()
        Parser.declareOnly(parser, noVar=True)

    args = [i.varType for i in parser.currentNode]
    fields = parser.currentNode.nodes

    typ.fields = [i.name for i in typ]

    typ.nodes = []
    parser.currentNode = tmp

    if decl:
        meth = parser.structs[parser.package][name].methods
        parser.structs[parser.package][name] = Struct(name, args, fields, gen)
        parser.structs[parser.package][name].methods = meth
        parser.structs[parser.package][name].package = parser.package

    Scope.decrScope(parser)
Example #13
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)
Example #14
0
def _resolve(self, tokens, filename, passN= 0 ):
    if self.hotswap and not ImportParser.shouldCompile(False, self.package, self):
        return

    self.filename = filename
    self.iter = 0

    self.tokens = tokens

    while self.iter < len(tokens) - 1 :
        b = self.thisToken().token

        if passN == 2:
            if b == "import":
                ImportParser.importParser(self, True)
            elif b == "def" :
                if self.indentLevel == 0:
                    nex = self.lookInfront()

                    Parser.addBookmark(self)
                    funcHead(self)
                    Parser.returnBookmark(self)
        elif passN == 1:
            if b == "import":
                ImportParser.importParser(self, True)

            elif b == "type":
                Parser.addBookmark(self)
                Struct.typeParser(self, decl= True)
                Parser.returnBookmark(self)

        elif passN == 0:
            if b == "type":
                Scope.addVar(Tree.Node(self), self, self.nextToken().token, Scope.Type(True, Types.StructInit(self.thisToken().token)))

                #"""
                self.structs[self.package][self.thisToken().token] = Struct.Struct(self.thisToken().token, [],[], {}, self)
                self.structs[self.package][self.thisToken().token].methods = {}
                #"""

        if b == "\n":
            Parser.addBookmark(self)
            Parser.newLine(self)
            Parser.returnBookmark(self)

        self.nextToken()

    for i in self.imports:
        if not i in self.allImports[self.package]:
            self.allImports[self.package].add(i)


    self.imports = []

    self.lineNumber = 1
    self.normalIndent = 0
Example #15
0
def validate(parser, tree):
    for i in tree:
        if type(i) is Tree.Lambda:
            Scope.incrScope(parser)
        if not i.isEnd():
            validate(parser, i)
        i.validate(parser)

    if type(tree) is Tree.Root:
        tree.validate(parser)
Example #16
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)
Example #17
0
def _resolve(self, tokens, filename, passN= 0 ):
    self.filename = filename
    self.iter = 0

    self.tokens = tokens

    while self.iter < len(tokens) - 1 :
        b = self.thisToken().token

        if passN == 2:
            if b == "import":
                ImportParser.importParser(self, True)
            elif b == "def" :
                if self.indentLevel == 0:
                    nex = self.lookInfront()

                    Parser.addBookmark(self)
                    funcHead(self)
                    Parser.returnBookmark(self)
        elif passN == 1:
            if b == "import":
                ImportParser.importParser(self, True)

            elif b == "type":
                Parser.addBookmark(self)
                Struct.typeParser(self, decl= True)
                Parser.returnBookmark(self)

        elif passN == 0:
            if b == "type":
                Scope.addVar(Tree.Node(self), self, self.nextToken().token, Scope.Type(True, Types.StructInit(self.thisToken().token)))

                self.structs[self.package][self.thisToken().token] = Struct.Struct(self.thisToken().token, [],[], {})
                self.structs[self.package][self.thisToken().token].methods = {}

        if b == "\n":
            Parser.addBookmark(self)
            Parser.newLine(self)
            Parser.returnBookmark(self)

        self.nextToken()

    for i in self.imports:
        if not i in self.allImports[self.package]:
            self.allImports[self.package].append(i)

    self.imports = []

    self.lineNumber = 1
    self.normalIndent = 0
Example #18
0
def parserMethodGen(parser, gen, struct):
    sgen = struct.generic

    if len(gen) > len(sgen):
        Error.parseError(parser, str(len(gen)-len(sgen))+" generic arguments too many")
    elif len(gen) < len(sgen):
        Error.parseError(parser, str(len(gen) - len(sgen)) + " generic arguments too few")

    newGen = coll.OrderedDict()
    for a, b in zip(gen, sgen):
        if gen[a].type != Types.All: Error.parseError(parser, "unexpected :")
        newGen[a] = sgen[b]
        Scope.changeType(parser, a, sgen[b])

    return newGen
Example #19
0
    def getConst(self, item):
        if self.typ.normalName != "":
            return self.typ.const[item]

        def setConst(index):
            def inner(newTyp):
                self.typ.const[item][index] = unificaction(
                    self.typ.const[item][index], newTyp, self.parser)
                typ = self.typ
                self.typ = Enum(typ.package, typ.name, typ.const, typ.generic)
                self.name = self.typ.name
                self.callback(self.typ)

            return inner

        parser = self.parser
        c = Scope.typeOfVar(Tree.PlaceHolder(self.parser), parser,
                            parser.package, item)

        if type(c) is FuncPointer:
            enum = c.returnType
            args = c.args
        else:
            enum = c
            args = []

        replaces = {}
        for i in enum.generic:
            replaces[i] = Unknown(parser,
                                  callback=setConst(i),
                                  typ=newT(parser))

        r = replaceT(enum, replaces)
        self.compareType(r)
        return self.typ.const[item]
Example #20
0
    def validate(self, parser):
        node = self
        package = self.package

        if self.init:
            self.isGlobal = self.owner.nodes[0].isGlobal
            createTyp = self.owner.nodes[0].varType
        else:
            self.isGlobal = Scope.isGlobal(parser, self.package, self.name)

            if type(self.nodes[0]) is Tree.ReadVar:
                if self.nodes[0].imutable:
                    self.nodes[0].error("cannot reassign to immutable variable "+self.nodes[0].name)
            elif type(self.nodes[0]) in [Tree.Field, Tree.ArrRead]:
                createTyp = self.nodes[0].nodes[0].type
                if not Types.isMutable(createTyp):
                    self.nodes[0].error("type "+str(createTyp)+" is not assignable")
            else:
                self.nodes[0].error("invalid syntax")

        if len(node.nodes) == 0:
           self.error( "expecting expression")
        if self.init:
            if len(node.nodes) > 1:
                self.error( "expecting single expression, not multiple")

            typ = node.nodes[0].type
        else:
            if len(node.nodes) > 2:
                self.error("expecting single expression, not multiple")
            typ = node.nodes[1].type

        if typ == Types.Null():
            self.nodes[0].error("cannot assign nothing")
Example #21
0
def funcBody(parser, name, names, types, brace, returnType, do):
    body = Tree.FuncBody(parser)
    body.name = name
    body.returnType = returnType
    body.package = parser.package
    body.do = do
    body.types = types

    brace.body = body

    parser.currentNode.addNode(body)
    parser.currentNode = body

    if not parser.sc and not SimplifyAst.isGenericFunc(brace):
        body.sc = False

        if parser.nextToken().token == "\n":
            Parser.callToken(parser)
        while not Parser.isEnd(parser):
            if parser.nextToken().token == "\n":
                Parser.callToken(parser)
        parser.currentNode = body.owner
        Scope.decrScope(parser)
        #print("should not compile", name)
        return body

    for i in range(len(names)):
        n = Tree.InitArg(names[i], parser)
        n.package = parser.package
        n.varType = types[i]
        n.imutable = not Scope.isMutable(parser, parser.package, names[i])
        body.addNode(n)

    parser.nextToken()
    Parser.callToken(parser)  #incase next case is newline

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

    ExprParser.endExpr(parser)

    parser.currentNode = body.owner

    Scope.decrScope(parser)
    return body
Example #22
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
Example #23
0
def parserMethodGen(parser, gen, struct):
    sgen = struct.generic

    if len(gen) > len(sgen):
        Error.parseError(
            parser,
            str(len(gen) - len(sgen)) + " generic arguments too many")
    elif len(gen) < len(sgen):
        Error.parseError(
            parser,
            str(len(gen) - len(sgen)) + " generic arguments too few")

    newGen = coll.OrderedDict()
    for a, b in zip(gen, sgen):
        if gen[a].type != Types.All: Error.parseError(parser, "unexpected :")
        newGen[a] = sgen[b]
        Scope.changeType(parser, a, sgen[b])

    return newGen
Example #24
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)
Example #25
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.interfaces[parser.package][name] = i

    Scope.decrScope(parser)
Example #26
0
    def parse(package, filename, cont, token):
        comment = token.token[4:-2]
        split = splitBy(comment)
        inCode = False

        for i in split:
            if len(i) > 0 and i[:3] == "```" and inCode:
                inCode = False
                cont.append(i)
            elif len(i) > 0 and i[:3] == "```" and not inCode:
                cont.append("```scala"+i[3:])
                inCode = True
            elif len(i) > 0 and i[0] == "@":
                name = i[1:]

                cont.append("```scala\n")


                if name in parser.structs[package]:
                    typ = parser.structs[package][name]
                    cont.append("type " + name + gen(typ.generic) + " =")
                    for c in Struct.offsetsToList(parser.structs[package][name].offsets):
                        cont.append("\n   " + c + ": " + typ.types[c].name + "")
                elif name in parser.interfaces[package]:
                    typ = parser.interfaces[package][name]

                    if type(typ) is Types.Interface:
                        cont.append("type " + name + " with\n")
                        for c in typ.types:
                            cont.append("   " + c + ": " + typ.types[c].name + "\n")
                    elif type(typ) is Types.Enum:
                        cont.append("type " + name + " either\n")
                        for c in typ.types:
                            args = typ.types[c]
                            if len(args) == 0:
                                cont.append("   " + c + "\n")
                            else:
                                cont.append("   " + c + "(" + ", ".join([d.name for d in args]) + ")\n")
                else:
                    try:

                        n = Scope.typeOfVar(PlaceHolder(package, filename, token), parser, package, name)
                        cont.append(name+": "+str(n))
                    except EOFError:
                        try:
                            PlaceHolder(package, filename, token).error("no variable named "+name)
                        except EOFError as e:
                            print(e, file=sys.stderr)
                            sys.exit()

                cont.append("\n```")
            else:
                cont.append(i)
Example #27
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)
Example #28
0
    def check(self, parser):
        if self.already:
            return
        name = ("do " if do else "") + "|" + ", ".join(
            [i.name for i in self.args]) + "| -> " + self.returnType.name

        self.already = True
        for i in self.args:
            if type(i) is Unknown:
                self.name = name
                return

        from TopCompiler import TypeInference
        from TopCompiler import Scope

        Scope.incrScope(parser)

        for (a, b) in zip(func.nodes[0], func.type.args):
            a.varType = b

        if type(self.returnType) is Unknown:
            TypeInference.infer(parser, func.nodes[0])
            TypeInference.infer(parser, func.nodes[1])

            Scope.decrScope(parser)

            if len(func.nodes[1]) == 0:
                typ = Types.Null()
            else:
                typ = func.nodes[1].nodes[-1].type
            self.returnType = typ
            func.nodes[1].returnType = typ
        else:
            TypeInference.infer(parser, func)

        name = ("do " if do else "") + "|" + ", ".join(
            [i.name for i in self.args]) + "| -> " + self.returnType.name
        self.name = name
Example #29
0
    def validate(self, parser):
        checkUseless(self)

        actReturnType = Types.Null()
        if self.returnType == Types.Null(): pass
        elif len(self.nodes) > 0:
            if self.nodes[-1].type == Types.Null():
                actReturnType = Types.Null()

            else:
                actReturnType = self.nodes[-1].type

        returnType = self.returnType
        name = self.name

        import AST as Tree

        try:
            returnType.duckType(parser,actReturnType,self, self.nodes[-1] if len(self.nodes) > 0 else Tree.Under(self),0)
        except EOFError as e:
            Error.beforeError(e, "Return Type: ")

        Scope.decrScope(parser)
Example #30
0
    def validate(self, parser):
        node = self
        package = self.package

        if type(self.owner) is Tree.InitStruct:
            return

        if self.init:
            self.isGlobal = Scope.isGlobal(parser, self.package, self.name)
            createTyp = self.createTyp
        else:
            if type(self.nodes[0]) is Tree.ReadVar:
                if self.nodes[0].imutable:
                    self.nodes[0].error(
                        "cannot reassign to immutable variable " +
                        self.nodes[0].name)
            elif type(self.nodes[0]) in [Tree.Field, Tree.ArrRead]:
                createTyp = self.nodes[0].nodes[0].type
                if not Types.isMutable(createTyp):
                    self.nodes[0].error("type " + str(createTyp) +
                                        " is not assignable")
            else:
                self.nodes[0].error("invalid syntax")

        if len(node.nodes) == 0:
            self.error("expecting expression")
        if self.init:
            if len(node.nodes) > 1:
                self.error("expecting single expression, not multiple")

            typ = node.nodes[0].type
        else:
            if len(node.nodes) > 2:
                self.error("expecting single expression, not multiple")
            typ = node.nodes[1].type

        if typ == Types.Null():
            self.nodes[0].error("cannot assign nothing")
Example #31
0
def _resolve(self, tokens, filename, passN=0):
    target = self.global_target
    if self.package != "main":
        self.global_target = "full"

    if self.hotswap and not ImportParser.shouldCompile(False, self.package,
                                                       self):
        return

    self.filename = filename
    self.iter = 0

    self.tokens = tokens

    while self.iter < len(tokens) - 1:
        b = self.thisToken().token

        if passN == 2:
            if b == "import":
                ImportParser.importParser(self, True)
            elif b == "from":
                ImportParser.fromParser(self, True)
            elif b == "def":
                if self.indentLevel == 0:
                    nex = self.lookInfront()

                    Parser.addBookmark(self)
                    funcHead(self)
                    Parser.returnBookmark(self)
        elif passN == 1:
            if b == "import":
                ImportParser.importParser(self, True)
            elif b == "from":
                ImportParser.fromParser(self, True)
            elif b == "type":
                Parser.addBookmark(self)
                Struct.typeParser(self, decl=True)
                Parser.returnBookmark(self)

        elif passN == 0:
            if b == "type":
                name = self.nextToken().token
                if name == "ext":
                    name = self.nextToken().token

                ofType = None
                gen = {}

                if self.nextToken().token == "[":
                    Scope.incrScope(self)
                    gen = FuncParser.generics(self, name)
                    Scope.decrScope(self)
                    ofType = self.thisToken().token
                else:
                    ofType = self.thisToken().token

                Scope.addVar(Tree.Node(self), self, name,
                             Scope.Type(True, Types.StructInit(name)))

                if ofType is None or ofType == "=":
                    #"""
                    self.structs[self.package][name] = Struct.Struct(
                        name, [], [], gen, self, self.package)
                    self.structs[self.package][name].methods = {}
                    #"""
                elif ofType == "either":
                    self.interfaces[self.package][name] = Types.Enum(
                        self.package, name, coll.OrderedDict(), gen)
                elif ofType == "with":
                    self.interfaces[self.package][name] = Types.Interface(
                        False, {}, name=self.package + "." + name)
                elif ofType == "is":
                    self.interfaces[self.package][name] = Types.Alias(
                        self.package, name, Types.Null(), gen)

        if b == "\n":
            Parser.addBookmark(self)
            Parser.newLine(self)
            Parser.returnBookmark(self)

        self.nextToken()

    for i in self.imports:
        if not i in self.allImports[self.package]:
            self.allImports[self.package].append(i)

    self.imports = []

    self.lineNumber = 1
    self.normalIndent = 0

    self.global_target = target
Example #32
0
 def validate(self, parser):
     Scope.incrScope(parser)
Example #33
0
def typeParser(parser, decl= False):
    name = parser.nextToken()

    Scope.incrScope(parser)


    if name.type != "identifier":
        Error.parseError(parser, "type name must be an identifier")
    name = name.token

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

    import collections as coll
    gen = coll.OrderedDict()

    if parser.nextToken().token == "[":
        gen = FuncParser.generics(parser, name)

    if parser.thisToken().token != "=":
        if parser.thisToken().token in ["with", "either", "is"]:
            tmp = parser.currentNode
            if parser.thisToken().token == "either":
                Enum.enumParser(parser, name, decl, gen)
            elif parser.thisToken().token == "is":
                Alias.aliasParser(parser, name, decl, gen)
            else:
                parser.currentNode = Tree.PlaceHolder(parser)
                Interface.traitParser(parser, name, decl, gen)
                parser.currentNode = tmp
            return

        Error.parseError(parser, "expecting =")
    tmp = parser.currentNode

    typ = Tree.Type(parser.package, name, parser)
    typ.package = parser.package
    typ.normalName = name

    tmp.addNode(typ)

    parser.currentNode = typ

    while not Parser.isEnd(parser):
        parser.nextToken()
        Parser.declareOnly(parser, noVar=True)

    args = [i.varType for i in parser.currentNode]
    fields = parser.currentNode.nodes

    typ.fields = [i.name for i in typ]

    typ.nodes = []
    parser.currentNode = tmp

    if decl:
        meth = parser.structs[parser.package][name].methods
        _types = parser.structs[parser.package][name]._types

        parser.structs[parser.package][name] = Struct(name, args, fields, gen, typ, parser.package)
        tmp =  parser.structs[parser.package][name]._types
        parser.structs[parser.package][name].methods = meth
        parser.structs[parser.package][name].package = parser.package
        parser.structs[parser.package][name]._types = _types
        _types.update(tmp)

        Scope.changeType(parser, name, parser.structs[parser.package][name] )

    typ.struct = parser.structs[parser.package][name]

    Scope.decrScope(parser)
Example #34
0
 def validate(self, parser):
     Scope.incrScope(parser)
Example #35
0
def parseLens(parser):
    #parser.nextToken()
    Scope.incrScope(parser)
    #lensType = Types.parseType(parser)
    Scope.decrScope(parser)

    place = Tree.Place(parser)

    lens = Tree.Lens(parser)
    lens.place = place

    parser.currentNode.addNode(lens)

    parser.currentNode = lens

    lens.addNode(place)

    #parser.nextToken()

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

    ExprParser.endExpr(parser)

    parser.currentNode = lens.owner

    B = Types.T("B", Types.All, "Lens")

    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)

    lens_typ = loop(lens.nodes[0])

    A = Types.T("A", lens_typ, "Lens")

    self = Types.Interface(False, {
        "query": Types.FuncPointer([A], B),
        "set": Types.FuncPointer([A, B], A),
        "toString": Types.FuncPointer([], Types.String(0)),
    },
                           coll.OrderedDict([("Lens.A", A), ("Lens.B", B)]),
                           name="Lens")

    Lens = Types.Interface(False, {
        "query": Types.FuncPointer([A], B),
        "set": Types.FuncPointer([A, B], A),
        "toString": Types.FuncPointer([], Types.String(0)),
    },
                           coll.OrderedDict([("Lens.A", A), ("Lens.B", B)]),
                           name="Lens")

    #lens.type = Types.Interface(False, {
    #    #   "query": Types.FuncPointer([i.lensType], i.nodes[0].type),
    #    "set": Types.FuncPointer([i.lensType, i.nodes[0].type], i.lensType),
    #})

    lens.type = Lens
Example #36
0
            case.nodes[0].error("no such variable "+case.nodes[0].name)
        pattern = typ.const[case.nodes[0].name]

        if len(pattern) < (len(case.nodes) - 1):
            case.nodes[-1].error(str((len(case.nodes) - 1) - len(pattern)) + " to many arguments")

        for iter in range(1, len(case.nodes)):
            checkCase(parser, case.nodes[iter], pattern[iter-1])
        case.nodes[0].type = Types.FuncPointer([], Types.Null(), do=False)

        if case.curry:
            case.nodes[-1].error("missing "+str(len(pattern) - (len(case.nodes)-1))+" arguments")

        case.type = typ
    elif type(case) is Tree.ReadVar and not first:
        Scope.addVar(case, parser, case.name, Scope.Type(True, typ))
    elif type(case) is Tree.ReadVar and first:
        if not (type(typ) is Types.Enum and case.name in typ.const):
            case.error("unknown pattern")

        case.type = typ
    elif type(case) is Tree.Operator and case.kind == "concat" and not case.curry and not case.partial:
        if not type(typ) is Types.String:
            case.nodes[0].error("unexpected string")
        if type(case.nodes[1]) is Tree.Tuple:
            Scope.addVar(case.nodes[1].nodes[0], parser, case.nodes[1].nodes[0].name, Scope.Type(True, typ))
        else:
            checkCase(parser, case.nodes[0], typ)
            checkCase(parser, case.nodes[1], typ)

        case.type = typ
Example #37
0
                                 str(len(pattern) -
                                     (len(case.nodes) - 1)) + " arguments")

        case.type = typ
    elif type(case) is Tree.Operator and case.kind == "as":
        if not typ.isType(Types.Interface):
            case.nodes[0].error("Cannot pattern match on type " + str(typ) +
                                "m as if it were an interface.")

        if not case.type.isType(Types.Pointer):
            case.error("Can only extract pointer type from interface")

        checkCase(parser, case.nodes[0], case.type)
    elif type(case) is Tree.ReadVar and case.name[0].lower() == case.name[0]:
        case.type = typ
        Scope.addVar(case, parser, case.name, Scope.Type(False, typ))
    elif type(case) is Tree.ReadVar:
        if not typ.isType(Types.Enum):
            case.error("cannot pattern match on type " + str(typ) +
                       ", as if it were a ADT")

        if not case.name in typ.const:
            case.error("ADT " + str(typ) + ", does not have case " + case.name)

        case.type = typ
    elif type(
            case
    ) is Tree.Operator and case.kind == "concat" and not case.curry and not case.partial:
        if not typ.isType(Types.String):
            case.nodes[0].error("unexpected string")
        if type(case.nodes[1]) is Tree.Tuple:
Example #38
0
def funcHead(parser):
    (name, names, types, header, returnType,
     do) = FuncParser.funcHead(parser, True)
    Scope.decrScope(parser)
Example #39
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:
            try:
                attachTyp = parser.interfaces[parser.package][name]
                if not type(attachTyp) is Types.Enum:
                    Error.parseError(
                        parser,
                        "no attachable data structure found, called " + name)

            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,
                         (attachTyp.normalName + "." 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:
                    try:
                        tmp = parser.interfaces[parser.package][name]
                        if not type(tmp) is Types.Enum:
                            raise KeyError

                        attachTyp = Types.replaceT(
                            tmp, parserMethodGen(parser, g, tmp))
                    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 (")

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

    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:
        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)

    header.do = 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, brace, returnType, do

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

    header.ftype = func
    if decl:
        if not dontAdd:
            Scope.addFunc(header, parser, name, func)

    return name, names, types, brace, returnType, do
Example #40
0
    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
Example #41
0
    def loop(n, o_iter):
        count = 0
        for i in n:
            if type(n) is Tree.Root:
                o_iter += 1

            if not sc and type(i) in [Tree.FuncStart, Tree.FuncBraceOpen, Tree.FuncBody]:
                count += 1
                continue

            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.Block, Tree.While]:
                Scope.incrScope(parser)

            if not (i.isEnd() or type(i) is Tree.MatchCase or (type(i) is Tree.Block and type(i.owner) is Tree.Match)):
                if not type(i) is Tree.Lambda:
                    loop(i, o_iter)

            if type(i) is Tree.Match:
                typ = i.nodes[0].type
                first = False
                for c in range(1,len(i.nodes),2):
                    body = i.nodes[c+1]

                    Scope.incrScope(parser)
                    Enum.checkCase(parser, i.nodes[c].nodes[0], typ, True)
                    loop(body, o_iter)
                    body.type = body.nodes[-1].type if len(body.nodes) > 0 else Types.Null()
                    Scope.decrScope(parser)
                    if first:
                        if body.type != first:
                            (body.nodes[-1] if len(body.nodes) > 0 else body).error(
                                "type mismatch in arms of match, " + str(body.type) + " and " + str(first))
                    else:
                        if len(i.nodes[2].nodes) > 0:
                            first = i.nodes[2].nodes[-1].type
                        else:
                            first = Types.Null()
                        i.nodes[2].type = first

                Enum.missingPattern(typ, i)
                i.type = first if first else Types.Null()

            elif type(i) is Tree.CreateAssign:
                if i.nodes[0].varType is None and i.nodes[0].name != "_":
                    if i.extern:
                        i.error("expecting type declaration, for external variable declaration")
                    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.global_target))
                        i.nodes[0].isGlobal = Scope.isGlobal(parser, i.nodes[0].package, i.nodes[0].name)
                if i.global_target != parser.global_target:
                    #print(i.nodes[0].name)
                    Scope.changeTarget(parser, i.nodes[0].name, i.global_target)
                    #print("this variable can only be used in a specific target", i.global_target)
            elif type(i) is Tree.FuncBody:
                Scope.decrScope(parser)
                def check(n, _i):
                    for c in n:
                        if type(c) is Tree.FuncCall:
                            if c.nodes[0].type.do and not _i.do and not c.partial and not c.curry:
                                c.nodes[0].error("cannot call function with side effects in a pure function")

                        if type(c) is Tree.FuncBody:
                            check(c, c)

                        elif not c.isEnd():
                            check(c, _i)
                check(i, i)
                if i.global_target != parser.global_target:
                    #print(i.name)
                    Scope.changeTarget(parser, i.name, i.global_target)
                    #print("this function can only be used in a specific target", i.global_target)

            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.owner.global_target))
                    i.isGlobal = Scope.isGlobal(parser, i.package, i.name)

            elif type(i) is Tree.ReadVar:
                if i.name == "newAtom":
                    if not (type(i.owner) is Tree.FuncCall and i.owner.nodes[0] == i and not i.owner.curry and not i.owner.partial):
                        i.error("expecting function call, with no currying or partial application")

                    if parser.atoms > 0:
                        i.error("can only have one atom per application")

                if not (type(i.owner) is Tree.Assign and type(i.owner.owner) is Tree.InitStruct and i.owner.nodes[0] == i):
                    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)

                    target = Scope.targetOfVar(i, parser, parser.package, self.name)

                    if target != parser.global_target:
                        root = tree.nodes[o_iter]

                        if type(root) is Tree.FuncBody:
                            tree.nodes[o_iter-1].global_target = target
                            tree.nodes[o_iter-2].global_target = target

                        root.global_target = target

                    elif tree.nodes[o_iter].global_target != target and target != "full":
                        realT = tree.nodes[o_iter].global_target
                        i.error("variable "+i.name+" is bound to target "+realT+" however, this variable is from target "+target)

            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, generic= self.type.generic, do= self.type.do)
                        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)

                    target = Scope.targetOfVar(i, parser, i.nodes[0].name, i.field)

                    if target != parser.global_target:
                        root = tree.nodes[o_iter]

                        if type(root) is Tree.FuncBody:
                            tree.nodes[o_iter-1].global_target = target
                            tree.nodes[o_iter-2].global_target = target

                        root.global_target = target

                    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 == "|>" or 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 i.kind == ">>":
                        if not type(a) is Types.FuncPointer:
                            self.nodes[1].error("right argument must be a function")
                        a = a.returnType

                    if not type(b) is Types.FuncPointer:
                        self.nodes[1].error("left argument must be a function")

                    if len(b.args) != 1:
                        self.nodes[1].error("expecting one function argument that matches return type of piped function")

                    try:
                        b.args[0].duckType(parser, a, self.nodes[0], self.nodes[1], 1)
                    except EOFError as e:
                        if i.kind == ">>":
                            Error.beforeError(e, "Function combining with: ")
                        else:
                            Error.beforeError(e, "Function piping to: ")

                    if i.kind == ">>":
                        a = self.nodes[0].type
                        self.type = Types.FuncPointer(a.args, b.returnType, do= a.do or b.do, generic=a.generic)
                    else:
                        self.type = b.returnType
                elif i.kind == "<-":
                    if i.unary:
                        try:
                            meth = i.nodes[0].type.types["unary_read"]
                        except:
                            meth = i.nodes[0].type.hasMethod(parser, "unary_read")

                        if meth:
                            i.type = meth.returnType
                            i.opT = i.nodes[0].type
                    else:
                        try:
                            meth = i.nodes[0].type.types["unary_read"]
                        except:
                            meth = i.nodes[0].type.hasMethod(parser, "unary_read")

                elif i.kind == "concat":
                    stringable = Types.Interface(False, {"toString": Types.FuncPointer([], Types.String(0))})
                    for c in i:
                        stringable.duckType(parser,c.type,i,i,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 = [("Operator.T", Types.All)]

                        returnT = T

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

                        i.opT = T
                        i.type = Types.FuncPointer([T,T], returnT, 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:
                c = i
                if i.nodes[0].name == "newAtom":
                    i = i.nodes[0]
                    if parser.hotswap:
                        parser.atomTyp.duckType(parser, i.owner.nodes[1].type, i.owner.nodes[1], i, 0)

                        f = Tree.Field(0, i.owner.nodes[1].type, i)
                        f.field = "arg"
                        f.type = parser.atomTyp
                        r = Tree.ReadVar("previousState", True, i)
                        r.package = ""
                        f.addNode(r)

                        i.owner.nodes[1] = f
                        f.owner = i.owner

                    parser.atomTyp = i.owner.nodes[1].type
                    parser.atoms += 1

                i = c

                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")

                do = i.nodes[0].type.do
                returnType = i.nodes[0].type.returnType

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

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

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

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

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

                        """
                        try:
                            normalTyp.duckType(parser, myNode.type, i, myNode, iter+1)
                        except EOFError as e:
                            normalTyp = resolveGen(xnormalTyp, myNode.type, {}, parser)
                            print(e)
                        """

                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(i.nodes)-1:]], Types.replaceT(i.nodes[0].type.returnType, generics), do= do)
                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), returnType, do= do)
            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 type(i.owner) is Tree.InitStruct:
                    pass
                elif not (type(i.owner) is Tree.CreateAssign and i.owner.nodes[0].varType is None):
                    if type(i.owner) is Tree.CreateAssign and i.owner.extern:
                        if not type(i.nodes[0].type) is Types.String:
                            i.error("expecting String")
                    else:
                        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 )")
                elif len(i.nodes) > 1:
                    i.type = Types.Tuple([c.type for c in i])
                else:
                    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")

                        count = 0
                        for c in arr.nodes[1:]:
                            if typ != c.type:
                                try:
                                    typ.duckType(parser, c.type, i, c, count)
                                except EOFError as e:
                                    Error.beforeError(e, "Element type in array: ")

                            count += 1

                    arr.type = Types.Array(arr.mutable, typ)
            elif type(i) is Tree.InitPack:
                parser.imports.append(i.package)
            elif type(i) is Tree.InitStruct:
                unary = i.unary
                if not unary:
                    typ = i.constructor.type
                    i.typ = typ

                    assign = True
                    if type(typ) is Struct.Struct:
                        s = typ
                        assign = False
                        i.paramNames = Struct.offsetsToList(s.offsets)
                    elif type(typ) is Types.Struct:
                        assign = True
                        s = typ
                    else:
                        i.constructor.error("type "+str(typ)+" can not be used as a constructor")

                    i.s = s
                    name = s.name

                    if len(s.types) < len(i.nodes) - 1:
                        c = str(len(i.nodes) - 1 - len(s.types))
                        i.error(("1 argument" if c == "1" else c + " arguments") + " too many")
                    elif not assign and len(s.types) > len(i.nodes) - 1:
                        c = str(len(s.types) + 1 - len(i.nodes))
                        i.error(("1 argument" if c == "1" else c + " arguments") + " too few")
                else:
                    assign = True


                gen = {}
                randomOrder = False
                order = {}

                for iter in range(0 if unary else 1, len(i.nodes)):
                    if type(i.nodes[iter]) is Tree.Assign:
                        randomOrder = True
                    elif assign:
                        i.nodes[iter].error("expecting =")

                    if not randomOrder:
                        order[i.paramNames[iter-1]] = i.nodes[iter]
                        myNode = i.nodes[iter]
                        normalTyp = s.fieldType[iter-1]
                    else:
                        if not type(i.nodes[iter]) is Tree.Assign:
                            i.nodes[iter].error("positional argument follows keyword argument")
                        if i.nodes[iter].nodes[0].name in order:
                            i.nodes[iter].nodes[0].error("duplicate parameter")
                        order[i.nodes[iter].nodes[0].name] = i.nodes[iter]
                        myNode = i.nodes[iter].nodes[1]
                        xname = i.nodes[iter].nodes[0].name

                        if not unary:
                            try:
                                normalTyp = s.types[xname]
                            except KeyError:
                                i.nodes[iter].nodes[0].error("type "+str(s)+" does not have the field "+ xname)

                    normalNode = i

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

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

                if not assign:
                    for c in order:
                        i.nodes[s.offsets[c]] = order[c]
                i.assign = assign

                if i.assign:
                    if unary:
                        types = {c: order[c].nodes[1].type for c in order}
                        i.type = Types.Interface(False, types)
                    else:
                        i.type = typ
                else:
                    i.type = Types.Struct(i.mutable, name, s.types, i.package, gen)

            elif type(i) is Tree.ArrRead:
                if not len(i.nodes) == 1:
                    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
                else:
                    i.error("expecting integer expression")
            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):
                    g = gen[c].type if type(gen[c]) is Types.T else gen[c]
                    g.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])
            elif type(i) is Tree.Lens:
                lensType = Types.Interface(False, {
                    "query": Types.FuncPointer([i.lensType], i.nodes[0].type),
                    "set": Types.FuncPointer([i.lensType, i.nodes[0].type], i.lensType),
                })

                i.type = lensType
            elif type(i) is Tree.Block:
                if len(i.nodes) > 0:
                    i.type = i.nodes[-1].type

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

            count += 1
Example #42
0
def funcHead(parser):
    (name, names, types, header, returnType, do) = FuncParser.funcHead(parser, True)
    Scope.decrScope(parser)
Example #43
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