def suite(self, node): node = L(node) node.code = [] for child in node: if DEBUG: print(child) node.code += pushExpr(child) return node
def keyget_expr(self, node): node = L(node) node.type = "u" leftType = getTypeSignature(node[0]) if leftType != "u": abort("Cannot use non 'u' %s as index to keyget" % leftType, node[0]) node.code = pushExpr(node[0]) node.code += ["KEYGET"] return node
def arealen_expr(self, node): node = L(node) node.type ="u" leftType = getTypeSignature(node[0]) if leftType != "u": abort("Cannot use non 'u' %s as index to arealen" % leftType, node[0]) node.code = pushExpr(node[0]) node.code += ["AREALEN"] return node
def term(self, node): node = L(node) node.code = pushExpr(node[0]) for i in range((len(node) - 1) // 2): nextop = node[1 + i * 2 + 1] leftType, rightType = ensurePrimitive(node[1].value, node[0], nextop) node.code += pushExpr(nextop) node.code += ['%s' % {'*':'MUL', '/':'DIV', '%':'MOD'}[node[1 + i * 2].value]] node.type = leftType return node
def arith_expr(self, node): node = L(node) node.code = pushExpr(node[0]) for i in range((len(node) - 1) // 2): nextop = node[1 + i * 2 + 1] leftType, rightType = ensurePrimitive(node[1].value, node[0], nextop) node.code += pushExpr(nextop) node.code += ['%s' % {'+':'ADD', '-':'SUB', '~':'NOT'}[node[1 + i * 2].value]] node.type = leftType return node
def doreturn(self, node): node = L(node) node.code = [] retType = getTypeSignature(node[0]) if compareTypes(retType, func["out"]): abort("Return type doesn't match function signature\nExpected %s, got %s" % (func["out"], retType)) node.type = retType node.code += pushExpr(node[0]) node.code += coda() return node
def funcall(self, node): if DEBUG: print("()", node) node = L(node) otherfuncname = node[0].children[0].value otherfunc = funcs[otherfuncname] node.type = otherfunc["out"] node.code = [] # CANNOT CHANGE STACK FRAME BOUNDARY; THEN pushExpr, because they depend on unmodified AREALEN! # Allocate parameter space if len(node) > 1: intypes = otherfunc["in"] for i, param in enumerate(node[1].children): paramsig = getTypeSignature(param) if compareTypes(intypes[i][0], paramsig): abort("Wrong types on function call, expected %s, got %s" % (intypes[i], paramsig)) node.code += pushExpr(param) node.code += asm("alloc(%i,%i)" % (MEM_STACK, inTypLen(otherfunc["in"]))) for i, param in enumerate(node[1].children[::-1]): paramsig = getTypeSignature(param) for index in range(types[paramsig]["len"]): # Write args to end of current stack frame node.code += asm("push(%i,sub(arealen(%i),%i))" % (MEM_STACK, MEM_STACK, index+i+1)) node.code += ["ROT2"] node.code += ["WRITE"] # Push return address # TODO do this dynamically with IP # XXX this doesn't work anymore anyway #label = generator.label() #node.code += ["PUSH %s" % label] node.code += ["PUSH 4", "HEADER"] node.code += ["PUSH 8", "ADD"] #XXX must add a few for this to work # XXX PUSH FUNC___!"§"otherfuncname (collisions) #node.code += ["PUSH %s" % otherfuncname, "JUMP"] node.code += asm("keyget(%i)" % nametoint(otherfuncname)) node.code += ["JUMP"] #node.code += [label+":"] # TODO now handle returned values! # Deallocate return values #XXX node.code += asm("dealloc(%i,%i)" % (MEM_STACK, typLen(otherfunc["out"]))) # Deallocate parameters node.code += asm("dealloc(%i,%i)" % (MEM_STACK, inTypLen(otherfunc["in"]))) return node
def getitem(self, node): node = L(node) leftType = getTypeSignature(node[0]) rightType = getTypeSignature(node[1]) if not leftType.startswith("*"): abort("Cannot index into non-pointer type %s of '%s'" % (leftType, node[0]), node) if rightType != "u": abort("Cannot index into pointer using non-u type %s of %s" % (rightType, node[1]), node) if DEBUG: print("[]", leftType, rightType) node.code = [] node.code += ["PUSH 0"] + pushExpr(node[0]) + pushExpr(node[1]) + ["ADD", "READ"] node.type = leftType[1:] return node
def string(self, node): # TODO allocate on heap node = L(node) node.type = "vector" arr = node[0].value[1:-1] new = stringToWords(arr) if DEBUG: print("String", new) node.code = [] node.code += asm("alloc(%i,%i)" % (MEM_HEAP, len(new))) for i, c in enumerate(new): node.code += asm("write(%i,sub(arealen(%i),%i),%i)" % (MEM_HEAP, MEM_HEAP, len(new)-i, c)) node.code += asm("push(sub(arealen(%i),%i),%i)" % (MEM_HEAP, len(new), len(new))) return node
def while_stmt(self, node): node = L(node) start_label = generator.label() end_label = generator.label() node.code = [start_label + ':'] if len(node) == 2: node.code += pushExpr(node[0]) node.code += ['PUSHR %s' % end_label] node.code += ['JZR'] node.code += node[1].code else: node.code += node[0].code node.code += ['PUSHR %s' % start_label] node.code += ['JUMPR'] node.code += [end_label + ':'] return node
def attr(self, node): if not hasType(node[0].value): abort("Name %s has no type" % node[0].value, node[0]) typ = getTypeSignature(node[0])#XXX if not typ in types: abort("%s's type is not a struct" % node[0].value, node[0]) subtype = getSubtype(typ, node[1].value) if subtype is None: abort("%s.'%s' is not a valid attribute" % (node[0].value, node[1].value), node[1]) node = L(node) node.code = [] for index in range(subtype["len"]): node.code += getAbsoluteOffset(node[0].value, subtype["offset"]+index) node.code += ["READ"] node.type = subtype["type"] return node
def if_stmt(self, node): node = L(node) node.code = [] node.code += pushExpr(node[0]) end_label = generator.label() if len(node) == 3: else_label = generator.label() node.code += ['PUSHR %s' % else_label] else: node.code += ['PUSHR %s' % end_label] node.code += ['JZR'] node.code += node[1].code if len(node) == 3: node.code += ['PUSHR %s' % end_label] node.code += ['JUMPR'] node.code += [else_label + ':'] node += node[2].code node.code += [end_label + ':'] return node
def dealloc_stmt(self, node): node = L(node) node.code = [] leftType = getTypeSignature(node[0]) if leftType != "u": abort("Cannot use non 'u' %s as index to dealloc" % leftType, node[0]) if len(node) == 1: node.code += ["PUSH 0"] node.code += pushExpr(node[0]) else: rightType = getTypeSignature(node[1]) if rightType != "u": abort("Cannot use non 'u' %s as size to dealloc" % rightType, node[1]) node.code += pushExpr(node[0]) node.code += pushExpr(node[1]) node.code += ["DEALLOC"] return node
def read(self, node): node = L(node) node.code = [] leftType = getTypeSignature(node[0]) if leftType != "u": abort("Cannot use non 'u' %s as index" % leftType, node[0]) if len(node) == 1: node.code += ["PUSH 0"] node.code += pushExpr(node[0]) else: rightType = getTypeSignature(node[1]) if rightType != "u": abort("Cannot use non 'u' %s as index" % rightType, node[1]) node.code += pushExpr(node[0]) node.code += pushExpr(node[1]) node.code += ["READ"] node.type = "u" return node
def write_stmt(self, node): node = L(node) node.code = [] leftType = getTypeSignature(node[0]) if leftType != "u": abort("Cannot use non 'u' %s as index" % leftType, node[0]) if len(node) == 2: abort("disabled write", node) node.code += ["PUSH 0"] node.code += pushExpr(node[0]) else: middleType = getTypeSignature(node[1]) if middleType != "u": abort("Cannot use non 'u' %s as index" % middleType, node[1]) node.code += pushExpr(node[0]) node.code += pushExpr(node[1]) node.code += pushExpr(node[-1]) node.code += ["WRITE"] return node
def tuple(self, node): node = L(node) node.code = [] if DEBUG: print("TUPLE", node, node.code) if isinstance(node, list): data = node tup = list(getTypeSignature(n) for n in data) node.type = tup#flatten(tup) else: data = node[1] tup = list(getTypeSignature(n) for n in data) #TODO compare name with actual type nametyp = types[node[0].value] if nametyp != tup: abort("Invalid type arguments: %s %s" % (nametyp, tup), node[0]) node.type = nametyp for n in data: node.code += pushExpr(n) return node
def comparison(self, node): node = L(node) if DEBUG: print("cmp", node) leftType, rightType = ensurePrimitive("cmp", node[0], node[2]) node.code = [] cmp = node[1].value if cmp in ["!=", "=="]: node.code += pushExpr(node[0]) node.code += pushExpr(node[2]) node.code += ["SUB"] if cmp == "==": node.code += ["NOT"] elif cmp == "<": node.code += pushExpr(node[0]) node.code += pushExpr(node[2]) node.code += ["CMP"] node.code += ["NOT"] elif cmp == ">=": node.code += pushExpr(node[2]) node.code += pushExpr(node[0]) node.code += ["CMP"] elif cmp == ">": node.code += pushExpr(node[0]) node.code += pushExpr(node[2]) node.code += ["CMP"] node.code += ["NOT"] elif cmp == "<=": node.code += pushExpr(node[2]) node.code += pushExpr(node[0]) node.code += ["CMP"] else: abort("Unknown comparison operator %s" % node[1].value, node[1]) #print("COMPARISON", cmp, node.code) node.type = "u" return node
def assign(self, node): if DEBUG: print("=", node) rightType = getTypeSignature(node[1]) if DEBUG: print("=", rightType) if hasType(node[0].value): leftType = getTypeSignature(node[0].value) if compareTypes(leftType, rightType): abort("Assignment type mismatch %s = %s" % (leftType, rightType), node) else: #print("New var", node[0].value) if isinstance(rightType, list) and len(rightType) > 1: raise NotImplemented("nope") elif len(rightType) == 0: abort("Cannot assign from () to something", node[0]) var[node[0].value] = {"type":rightType} #node.code += [["_RESERVE", node[0].value]] #print(types,var[node[0].value]) node = L(node) node.code = [] """ node.code += getAbsoluteOffset(node[0].value) node.code += getAbsoluteOffset(node[1].value) node.code += rightType["len"] node.code += "MEMCOPY" """ node.code += pushExpr(node[1]) for index in range(types[rightType]["len"]-1, -1, -1): # composite assignment somewhere else! node.code += getAbsoluteOffset(node[0].value, index) node.code += ["ROT2"] node.code += ["WRITE"] return node
def funcbody(self, node): node = L(node) node.code = [] # Allocate stack frame #print("RET", func["out"]) # Calculate stack frame size # + return address + stack frame framesize = varLen() + 2#XXX retlen + # Allocate stack frame node.code += asm("alloc(%i,%i)" % (MEM_STACK, framesize)) # Write current stack frame address to second last item of stack frame node.code += asm("write(%i,sub(arealen(%i),2),read(%i,0))" % (MEM_STACK, MEM_STACK, MEM_STACK)) # Write return address from stack to end of stack frame node.code += asm("write(%i,sub(arealen(%i),1),rot2)" % (MEM_STACK, MEM_STACK)) # Write stack frame address to 0:0 node.code += asm("write(%i,0,sub(arealen(%i), %i))" % (MEM_STACK, MEM_STACK, framesize)) # Put last index of area on stack #node.code += ["PUSH 0"] #node.code += ["PUSH 0", "arealen", "PUSH 1", "SUB"] # Save return address in frame #node.code += ["ROT2", "WRITE"] if DEBUG: print(funcname, node[0]) node.code += node[0].code node.code += ecoda() code = "\n".join(node.code) #XXX check for jump at end of function! return code
def memorylen_expr(self, node): node = L(node) node.type = "u" node.code = ["MEMORYLEN"] return node
def doyield(self,node): node = L(node) node.code = [] #node.code += pushExpr(node[0]) node.code += ["YIELD"] return node
def expr(self, node): node = L(node) node.code = [] node.type = getTypeSignature(node[0]) node.code = pushExpr(node[0]) return node
def funcname_expr(self, node): node = L(node) node.type = "u" node.code = ["PUSH %i" % nametoint(node[0].value)] return node
def area_stmt(self, node): node = L(node) node.code = ["AREA"] return node
def compound_stmt(self, node): node = L(node) node.code = pushExpr(node[0]) return node
def run(self, node): node = L(node) #node.code = asm("push(99999999999,99999999999)") node.code = pushExpr(node[0]) node.code += ["RUN"] return node
def listmaker(self, node): node = L(node) node.type = ["u"] * len(node) return node
def number(self, node): node = L(node) node.type = "u" #TODO make sure u is in range node.code = ["PUSH %s" % node[0].value] return node
def simple_stmt(self, node): node = L(node) node.code = pushExpr(node[0]) return node