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)
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)
def packDec(parser, name, pack= False): import os parser.opackage = name parser.package = os.path.basename(name) if pack: Scope.addPackage(parser, name)
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)
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)
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)
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
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)
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")
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
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)
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)
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
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)
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)
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
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
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]
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")
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
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
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
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)
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)
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)
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)
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
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)
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")
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
def validate(self, parser): Scope.incrScope(parser)
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)
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
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
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:
def funcHead(parser): (name, names, types, header, returnType, do) = FuncParser.funcHead(parser, True) Scope.decrScope(parser)
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
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
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
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