def generateBuiltinFuncs(): builtin_functions = OrderedDict() for f_id, f_list in BUILTIN_FUNCTIONS.items(): builtin_functions[(FunUniq.FUNC, f_id)] = [] for typesig_str, _ in f_list: vals = typesig_str.split() if vals[0] == '->': from_types = [] to_type = abstractToConcreteType((vals[1])) else: from_types = abstractToConcreteType(vals[0]) to_type = abstractToConcreteType(vals[2]) builtin_functions[(FunUniq.FUNC, f_id)].append({ 'type': AST.FUNTYPE(from_types=[] if len(from_types) == 0 else [AST.TYPE(val=from_types[0])], to_type=AST.TYPE(val=to_type[0])), 'module': BUILTINS_NAME, 'orig_id': f_id, 'fixity': None, 'kind': FunKind.FUNC }) return builtin_functions
def StmtIfElse(): yield ps.token(TOKEN.IF) yield ps.token(TOKEN.PAR_OPEN) condition = yield Exp yield ps.token(TOKEN.PAR_CLOSE) yield ps.token(TOKEN.CURL_OPEN) if_contents = yield ps.many(Stmt) yield ps.token(TOKEN.CURL_CLOSE) first_cond = AST.CONDBRANCH(expr=condition, stmts=if_contents) elifs = yield ps.many(StmtElif) elses = yield ps.times(StmtElse, 0, 1) return AST.IFELSE(condbranches=[first_cond, *elifs, *elses])
def abstractToConcreteType(abstract_type): if abstract_type == 'T': return [ AST.BASICTYPE(type_id=Token(Position(), TOKEN.TYPE_IDENTIFIER, b)) for b in BASIC_TYPES ] elif abstract_type in BASIC_TYPES: return [ AST.BASICTYPE(type_id=Token(Position(), TOKEN.TYPE_IDENTIFIER, abstract_type)) ] elif abstract_type == '[T]': return [ AST.LISTTYPE(type=AST.TYPE(val=AST.BASICTYPE( type_id=Token(Position(), TOKEN.TYPE_IDENTIFIER, b)))) for b in BASIC_TYPES ] elif abstract_type in ['[' + x + ']' for x in BASIC_TYPES]: return [ AST.LISTTYPE(type=AST.TYPE(val=AST.BASICTYPE(type_id=Token( Position(), TOKEN.TYPE_IDENTIFIER, abstract_type[1:-1])))) ] elif abstract_type in VOID_TYPE: return [Token(Position(), TOKEN.TYPE_IDENTIFIER, "Void")] else: raise Exception( "Unknown abstract type encountered in builtin operator table: %s" % abstract_type)
def FunCall(): fname = yield ps.token(TOKEN.IDENTIFIER) yield ps.token(TOKEN.PAR_OPEN) found_args = yield ps.times(ActArgs, 0, 1) found_args = found_args[0] if len(found_args) > 0 else [] yield ps.token(TOKEN.PAR_CLOSE) return AST.FUNCALL(id=fname, kind=FunKind.FUNC, args=found_args)
def TupType(): yield ps.token(TOKEN.PAR_OPEN) el1 = yield Type yield ps.token(TOKEN.COMMA) el2 = yield Type yield ps.token(TOKEN.PAR_CLOSE) return AST.TUPLETYPE(a=el1, b=el2)
def InfixOpDecl(): side = yield (ps.token(TOKEN.INFIXL) ^ ps.token(TOKEN.INFIXR)) if side.typ is TOKEN.INFIXL: found_kind = FunKind.INFIXL elif side.typ is TOKEN.INFIXR: found_kind = FunKind.INFIXR else: raise Exception("Should never happen") found_fixity = yield ps.token(TOKEN.INT) operator = yield ps.token(TOKEN.OP_IDENTIFIER) yield ps.token(TOKEN.PAR_OPEN) a = yield ps.token(TOKEN.IDENTIFIER) yield ps.token(TOKEN.COMMA) b = yield ps.token(TOKEN.IDENTIFIER) yield ps.token(TOKEN.PAR_CLOSE) typesig = yield ps.times(InfFunTypeSig, 0, 1) typesig = typesig[0] if len(typesig) > 0 else None yield ps.token(TOKEN.CURL_OPEN) decls = yield ps.many(VarDecl) found_stmts = yield ps.many1(Stmt) yield ps.token(TOKEN.CURL_CLOSE) return AST.FUNDECL(kind=found_kind, fixity=found_fixity, id=operator, params=[a, b], type=typesig, vardecls=decls, stmts=found_stmts)
def typecheck_stmts(func, symbol_table, ext_table): for vardecl in func['def'].vardecls: _, vardecl.expr = typecheck(vardecl.expr, vardecl.type.val, symbol_table, ext_table, func) stmts = list(reversed(func['def'].stmts)) ast_boolnode = AST.BASICTYPE(type_id=Token(Position(), TOKEN.TYPE_IDENTIFIER, "Bool")) while len(stmts) > 0: stmt = stmts.pop() if type(stmt.val) == AST.ACTSTMT: typecheck_actstmt(stmt.val, symbol_table, ext_table, func) elif type(stmt.val) == AST.IFELSE: for b in stmt.val.condbranches: if b.expr is not None: _, b.expr = typecheck(b.expr, ast_boolnode, symbol_table, ext_table, func) stmts.extend(list(reversed(b.stmts))) elif type(stmt.val) == AST.LOOP: if stmt.val.cond is not None: _, stmt.val.cond = typecheck(stmt.val.cond, ast_boolnode, symbol_table, ext_table, func) if stmt.val.init is not None: typecheck_actstmt(stmt.val.init, symbol_table, ext_table, func) if stmt.val.update is not None: typecheck_actstmt(stmt.val.update, symbol_table, ext_table, func) stmts.extend(list(reversed(stmt.val.stmts))) elif type(stmt.val) == AST.RETURN: if stmt.val.expr is not None: _, stmt.val.expr = typecheck(stmt.val.expr, func['type'].to_type.val, symbol_table, ext_table, func)
def ExpSubTup(): yield ps.token(TOKEN.PAR_OPEN) a = yield Exp b = yield ExpClose if b is None: return a else: return AST.TUPLE(a=a, b=b)
def StmtElif(): yield ps.token(TOKEN.ELIF) yield ps.token(TOKEN.PAR_OPEN) condition = yield Exp yield ps.token(TOKEN.PAR_CLOSE) yield ps.token(TOKEN.CURL_OPEN) contents = yield ps.many(Stmt) yield ps.token(TOKEN.CURL_CLOSE) return AST.CONDBRANCH(expr=condition, stmts=contents)
def VarDecl(): typ = yield (ps.token(TOKEN.VAR) | Type) typ = None if type(typ) == Token and typ.typ == TOKEN.VAR else typ #print(typ) varname = yield ps.token(TOKEN.IDENTIFIER) yield ps.token(TOKEN.OP_IDENTIFIER, cond=(lambda x: x == "=")) found_expr = yield Exp yield ps.token(TOKEN.SEMICOLON) return AST.VARDECL(type=typ, id=varname, expr=found_expr)
def generateBuiltinTypesyns(): temp = OrderedDict() for name, def_str in HIGHER_BUILTIN_TYPES.items(): temp[(name, BUILTINS_NAME)] = OrderedDict([ ('def_type', AST.TYPE(val=abstractToConcreteType(def_str)[0])), ('orig_id', name), ('decl', None) ]) return temp
def StmtWhile(): yield ps.token(TOKEN.WHILE) yield ps.token(TOKEN.PAR_OPEN) condition = yield Exp yield ps.token(TOKEN.PAR_CLOSE) yield ps.token(TOKEN.CURL_OPEN) contents = yield ps.many(Stmt) yield ps.token(TOKEN.CURL_CLOSE) return AST.LOOP(init=None, cond=condition, update=None, stmts=contents)
def mergeCustomOps(op_table, symbol_table, module_name): for x in symbol_table.functions: f = symbol_table.functions[x] if x[0] is FunUniq.INFIX: if x[1] not in op_table['infix_ops']: op_table['infix_ops'][x[1]] = (f[0]['def'].fixity.val, f[0]['def'].kind, []) for o in f: if op_table['infix_ops'][x[1]][0] == o[ 'def'].fixity.val and op_table['infix_ops'][ x[1]][1] == o['def'].kind: ft = AST.FUNTYPE(from_types=[ o['type'].from_types[0].val, o['type'].from_types[1].val ], to_type=o['type'].to_type.val) cnt = 0 for ot in op_table['infix_ops'][x[1]][2]: if AST.equalVals(ft, ot): cnt += 1 if cnt == 0: op_table['infix_ops'][x[1]][2].append( (ft, module_name)) else: ERROR_HANDLER.addError(ERR.DuplicateOpDef, [o['def'].id.val, o['def'].id]) else: ERROR_HANDLER.addError(ERR.InconsistentOpDecl, [o['def'].id.val, o['def'].id]) elif x[0] is FunUniq.PREFIX: if x[1] not in op_table['prefix_ops']: op_table['prefix_ops'][x[1]] = [] for o in f: op_table['prefix_ops'][x[1]].append( (AST.FUNTYPE(from_types=[o['type'].from_types[0].val], to_type=o['type'].to_type.val), module_name))
def FunDecl(): fname = yield ps.token(TOKEN.IDENTIFIER) yield ps.token(TOKEN.PAR_OPEN) args = yield ps.times(FArgs, 0, 1) args = args[0] if len(args) > 0 else args yield ps.token(TOKEN.PAR_CLOSE) typesig = yield ps.times(FunTypeSig, 0, 1) typesig = typesig[0] if len(typesig) > 0 else None yield ps.token(TOKEN.CURL_OPEN) decls = yield ps.many(VarDecl) found_stmts = yield ps.many1(Stmt) yield ps.token(TOKEN.CURL_CLOSE) return AST.FUNDECL(kind=FunKind.FUNC, fixity=None, id=fname, params=args, type=typesig, vardecls=decls, stmts=found_stmts)
def StmtFor(): yield ps.token(TOKEN.FOR) yield ps.token(TOKEN.PAR_OPEN) initial = yield ps.times(ActStmt, 0, 1) initial = initial[0] if len(initial) > 0 else None yield ps.token(TOKEN.SEMICOLON) condition = yield ps.times(Exp, 0, 1) condition = condition[0] if len(condition) > 0 else None yield ps.token(TOKEN.SEMICOLON) update = yield ps.times(ActStmt, 0, 1) update = update[0] if len(update) > 0 else None yield ps.token(TOKEN.PAR_CLOSE) yield ps.token(TOKEN.CURL_OPEN) contents = yield ps.many(Stmt) yield ps.token(TOKEN.CURL_CLOSE) return AST.LOOP(init=initial, cond=condition, update=update, stmts=contents)
def PrefixOpDecl(): yield ps.token(TOKEN.PREFIX) operator = yield ps.token(TOKEN.OP_IDENTIFIER) yield ps.token(TOKEN.PAR_OPEN) varname = yield ps.token(TOKEN.IDENTIFIER) yield ps.token(TOKEN.PAR_CLOSE) typesig = yield ps.times(PreFunTypeSig, 0, 1) typesig = typesig[0] if len(typesig) > 0 else None yield ps.token(TOKEN.CURL_OPEN) decls = yield ps.many(VarDecl) found_stmts = yield ps.many1(Stmt) yield ps.token(TOKEN.CURL_CLOSE) return AST.FUNDECL(kind=FunKind.PREFIX, fixity=None, id=operator, params=[varname], type=typesig, vardecls=decls, stmts=found_stmts)
def import_headers(json_string): # Can return exception, so put in try-except load_packet = json.loads(json_string) temp_packet = {} temp_packet["depends"] = load_packet["depends"] temp_packet["globals"] = OrderedDict([(k, parse_type(v)) for k, v in load_packet["globals"]]) temp_packet["typesyns"] = OrderedDict([ (k, parse_type(v)) for k, v in load_packet["typesyns"] ]) temp_packet["functions"] = OrderedDict() for (uq, k), fix, kind, from_ts, to_t in load_packet["functions"]: if (FunUniq[uq], k) not in temp_packet["functions"]: temp_packet["functions"][(FunUniq[uq], k)] = [] temp_packet["functions"][(FunUniq[uq], k)].append({ "fixity": fix, "kind": FunKind[kind], "type": AST.FUNTYPE(from_types=list(map(parse_type, from_ts)), to_type=parse_type(to_t)) }) return temp_packet
def tokenToNode(token): if token.typ == TOKEN.INT: node = AST.BASICTYPE(type_id=Token(Position(), TOKEN.TYPE_IDENTIFIER, "Int")) node._start_pos = Position() return node elif token.typ == TOKEN.CHAR: node = AST.BASICTYPE(type_id=Token(Position(), TOKEN.TYPE_IDENTIFIER, "Char")) node._start_pos = Position() return node elif token.typ == TOKEN.BOOL: node = AST.BASICTYPE(type_id=Token(Position(), TOKEN.TYPE_IDENTIFIER, "Bool")) node._start_pos = Position() return node elif token.typ == TOKEN.STRING: node = AST.LISTTYPE(type=AST.TYPE(val=AST.BASICTYPE(type_id=Token(Position(), TOKEN.TYPE_IDENTIFIER, "Char")))) node._start_pos = Position() return node elif token.typ == TOKEN.EMPTY_LIST: node = AST.BASICTYPE(type_id=Token(Position(), TOKEN.TYPE_IDENTIFIER, "[]")) node._start_pos = Position() return node else: raise Exception('Unexpected token type encountered')
def IdField(): i = yield ps.token(TOKEN.IDENTIFIER) found_fields = yield ps.many(ps.token(TOKEN.ACCESSOR)) return AST.VARREF(id=i, fields=found_fields)
def Decl(): found_val = yield VarDecl ^ FunDecl ^ TypeSyn ^ PrefixOpDecl ^ InfixOpDecl return AST.DECL(val=found_val)
def ImportName(): found_name = yield AnyId found_alias = yield ps.times(ps.token(TOKEN.AS) >> AnyId, 0, 1) found_alias = found_alias[0] if len(found_alias) > 0 else None return AST.IMPORTNAME(name=found_name, alias=found_alias)
def ActStmt(): found_val = yield Ass ^ FunCall return AST.ACTSTMT(val=found_val)
def Ass(): var = yield IdField yield ps.token(TOKEN.OP_IDENTIFIER, cond=(lambda x: x == "=")) expression = yield Exp return AST.ASSIGNMENT(varref=var, expr=expression)
def StmtElse(): yield ps.token(TOKEN.ELSE) yield ps.token(TOKEN.CURL_OPEN) contents = yield ps.many(Stmt) yield ps.token(TOKEN.CURL_CLOSE) return AST.CONDBRANCH(expr=None, stmts=contents)
def PrefixOpExp(): op = yield ps.token(TOKEN.OP_IDENTIFIER) exp = yield ConvExp return AST.FUNCALL(kind=FunKind.PREFIX, id=op, args=[AST.DEFERREDEXPR(contents=[exp])])
def Exp(): a = yield ConvExp b = yield ps.many(ExpMore) b = flatten(b) return AST.DEFERREDEXPR(contents=[a, *b])
def StmtContinue(): yield ps.token(TOKEN.CONTINUE) yield ps.token(TOKEN.SEMICOLON) return AST.CONTINUE()
def StmtBreak(): yield ps.token(TOKEN.BREAK) yield ps.token(TOKEN.SEMICOLON) return AST.BREAK()
def StmtRet(): yield ps.token(TOKEN.RETURN) found_expr = yield ps.times(Exp, 0, 1) found_expr = found_expr[0] if len(found_expr) > 0 else None yield ps.token(TOKEN.SEMICOLON) return AST.RETURN(expr=found_expr)
def AllImport(): yield ps.token(TOKEN.IMPORTALL) found_name = yield ps.token(TOKEN.FILENAME) return AST.IMPORT(name=found_name, importlist=None)