Add := Object clone do( newSlot("result") newSlot("val1") newSlot("val2") asString := method(result .. " := add " .. val1 .. " " .. val2) ) BasicBlock := Object clone do( newSlot("name") newSlot("function") newSlot("instructions") newSlot("variables") init := method( instructions = list variables = Map clone ) asString := method( name .. ":\n" ..( instructions map(i, " " .. i asString) join("\n") ) ) interpret := method(functionEval, nil ) asSimpleString := method( resend .. "_" .. name ) namedVariable := method(name, Variable clone setName(name) setIndex(variables at(name)) ) resultVariable := method(name, Variable clone setName(name) setIndex( i := variables at(name) if(i == nil, i = variables size variables atPut(name, i) ) i ) ) parseInstruction := method(m, if(m name == "setSlot", args := InstructionArgs with(m argAt(1)) setFunction(function) setBasicBlock(self) result := resultVariable(m argAt(0) cachedResult) instructions append( loop( if(m argAt(1) name == "phi", break(Phi clone setResult(result) setIncoming(args phiListAt(0))) ) if(m argAt(1) name == "add", break(Add clone setResult(result) setVal1(args valueAt(0)) setVal2(args valueAt(1))) ) if(m argAt(1) name == "seteq", break(Seteq clone setResult(result) setVal1(args valueAt(0)) setVal2(args valueAt(1))) ) writeln(name, ": ", m argAt(1) name, ": ", args) break ) ) , args := InstructionArgs with(m) setFunction(function) setBasicBlock(self) instructions append( loop( if(m name == "br", if(args size == 1, break(Br clone setDest(args labelAt(0))) , break(Brc clone setCond(args valueAt(0)) setTrueDest(args labelAt(1)) setFalseDest(args labelAt(2))) ) ) if(m name == "ret", if(args at(0) name == "void", break(Ret clone) , break(RetValue clone setValue(args valueAt(0))) ) ) writeln(name, ": ", m name, ": ", args) break ) ) ) ) ) Brc := Object clone do( newSlot("cond") newSlot("trueDest") newSlot("falseDest") asString := method("br " .. cond .. " " .. trueDest name .. " " .. falseDest name) ) Br := Object clone do( newSlot("dest") asString := method("br " .. dest name) ) FunctionEval := Object clone do( newSlot("exit", false) newSlot("returnValue") newSlot("next") interpret := method( while(exit not, next interpret(self) ) returnValue ) ) function := method( Function clone parseBlocks(call message argAt(0)) ) Message isTerminatorInstruction := method( list("ret", "br", "switch", "unwind", "unreachable") contains(name) or( name ==("setSlot") and(argAt(1) name == "invoke") ) ) Message isLabel := method( name endsWithSeq(":") ) Function := Object clone do( newSlot("blocks") newSlot("firstBlock") init := method( blocks = Map clone ) asString := method( "first = " .. firstBlock name .. "\n" ..( blocks values map(asString) join("\n") ) ) interpret := method( FunctionEval clone setNext(firstBlock) interpret ) unnamedBlock := method( b := BasicBlock clone setFunction(self) if(firstBlock == nil, firstBlock = b ) b ) namedBlock := method(name, b := blocks at(name) if(b == nil, b := unnamedBlock setName(name) blocks atPut(name, b) ) b ) parseBlocks := method(m, currentBlock := nil startBlock := true while(m, if(startBlock, if(m isLabel, label := m name slice(0, -1) currentBlock = namedBlock(label) , currentBlock = unnamedBlock currentBlock parseInstruction(m) ) , if(m isLabel, writeln("Labels which isn't after a terminator instruction: '", m name, "'. Ignoring this label.") , currentBlock parseInstruction(m) ) ) startBlock = m isTerminatorInstruction m = m next ) self ) ) Message attachedList := method( r := list m := attached while(m, r append(m) m = m attached ) r ) InstructionArgs := Object clone do( newSlot("args") newSlot("function") newSlot("basicBlock") with := method(m, self clone setArgs(m attachedList) ) size := method( args size ) at := method(i, args at(i) ) labelAt := method(i, labelForMsg(at(i)) ) labelForMsg := method(m, function namedBlock(m name) ) valueAt := method(i, valueForMsg(at(i), basicBlock) ) valueForMsg := method(m, bb, if(m cachedResult, Literal clone setValue(m cachedResult) , bb namedVariable(m name) ) ) phiListAt := method(i, vl := ValueLabelList clone m := at(i) argAt(0) while(m, bb := labelForMsg(m attached) vl add(valueForMsg(m, bb), bb) m := m next ) vl ) asString := method( args map(name) join(" ") ) ) Literal := Object clone do( newSlot("value") asString := method(value asString) ) doFile("function.io") function( loopHeader: br loop loop: i := phi [0 loopHeader; nextI loop] sum := phi [0 loopHeader; nextSum loop] nextI := add i 1 nextSum := add sum i c := seteq i 10 br c done loop done: ret sum ) println Phi := Object clone do( newSlot("result") newSlot("incoming") asString := method(result .. " := phi " .. incoming) ) Ret := Object clone do( asString := method("ret void") ) RetValue := Object clone do( newSlot("value") asString := method("ret " .. value) ) Seteq := Object clone do( newSlot("result") newSlot("val1") newSlot("val2") asString := method(result .. " := seteq " .. val1 .. " " .. val2) ) ValueLabelList := Object clone do( newSlot("items") init := method( items = list ) ValueLabel := Object clone do( newSlot("value") newSlot("label") asString := method(value .. " " .. label name) ) add := method(value, label, items append(ValueLabel clone setValue(value) setLabel(label)) ) asString := method("[ " .. items map(asString) join("; ") .. " ]") ) Variable := Object clone do( newSlot("name") newSlot("index") asString := method(name) )