move boolean output and character input to subroutine, change memlib comments
This commit is contained in:
parent
04489721f7
commit
eae3c68b51
|
@ -87,6 +87,15 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
|||
try {
|
||||
String memlib = new String(Files.readAllBytes(ToolChain.PATH.resolve("memlib.iloc"))); //$NON-NLS-1$
|
||||
prog = Assembler.instance().assemble(memlib);
|
||||
|
||||
String stdlib = new String(Files.readAllBytes(ToolChain.PATH.resolve("stdlib.iloc"))); //$NON-NLS-1$
|
||||
Program prog2 = Assembler.instance().assemble(stdlib);
|
||||
try {
|
||||
for (Instr instr : prog2.getInstr())
|
||||
prog.addInstr(instr);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace(System.err);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -823,88 +832,30 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
|||
|
||||
@Override
|
||||
public Reg visitRead(ReadContext ctx) {
|
||||
if (ctx.variable().size() > 1) {
|
||||
Reg res = null;
|
||||
for (VariableContext expr : ctx.variable()) {
|
||||
visit(expr);
|
||||
|
||||
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) {
|
||||
regPool.withReg((temp) -> {
|
||||
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr)))
|
||||
res = regPool.withReg((temp) -> {
|
||||
emit("", OpCode.in, new Str(""), temp); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
Reg addr = visit(expr);
|
||||
emit("save to var " + expr.getText(), OpCode.store, temp, addr); //$NON-NLS-1$
|
||||
});
|
||||
} else if (SimpleType.CHAR.equals(an.types.get(expr))) {
|
||||
// Get input until at least 1 character
|
||||
Label getTarget = makeLabel("lcin_l"); //$NON-NLS-1$
|
||||
Label continueTarget = makeLabel("lcin_e"); //$NON-NLS-1$
|
||||
|
||||
regPool.withReg((temp, count) -> {
|
||||
emit("", getTarget, OpCode.cin, new Str("")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
emit("str length", OpCode.pop, count); //$NON-NLS-1$
|
||||
emit("repeat if 0 length", OpCode.cbr, count, continueTarget, getTarget); //$NON-NLS-1$
|
||||
|
||||
// Get character
|
||||
emit("pop whole string", continueTarget, OpCode.cpop, temp); //$NON-NLS-1$
|
||||
else if (SimpleType.CHAR.equals(an.types.get(expr)))
|
||||
res = regPool.withReg((temp) -> {
|
||||
emit("call stdcin", OpCode.loadI, new Num(prog.size() + 3), temp); //$NON-NLS-1$
|
||||
emit("call stdcin", OpCode.push, temp); //$NON-NLS-1$
|
||||
emit("call stdcin", OpCode.jumpI, new Label("stdcin")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
emit("get character", OpCode.cpop, temp); //$NON-NLS-1$
|
||||
Reg addr = visit(expr);
|
||||
emit("save to var " + expr.getText(), OpCode.cstore, temp, addr); //$NON-NLS-1$
|
||||
|
||||
// Pop all remaining characters
|
||||
Label loopTarget = makeLabel("lcpop_l"); //$NON-NLS-1$
|
||||
Label iterTarget = makeLabel("lcpop_c"); //$NON-NLS-1$
|
||||
Label stopTarget = makeLabel("lcpop_e"); //$NON-NLS-1$
|
||||
emit("pop remaining", loopTarget, OpCode.subI, count, new Num(1), temp); //$NON-NLS-1$
|
||||
emit("pop remaining", OpCode.cbr, count, iterTarget, stopTarget); //$NON-NLS-1$
|
||||
emit("pop remaining", iterTarget, OpCode.cpop, temp); //$NON-NLS-1$
|
||||
emit("pop remaining", OpCode.jumpI, loopTarget); //$NON-NLS-1$
|
||||
emit("pop remaining", stopTarget, OpCode.nop); //$NON-NLS-1$
|
||||
});
|
||||
} else {
|
||||
else
|
||||
emit("reading unknown type", OpCode.haltI, new Num(0x72656164)); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
} else {
|
||||
VariableContext expr = ctx.variable(0);
|
||||
|
||||
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) {
|
||||
return regPool.withReg((result) -> {
|
||||
emit("", OpCode.in, new Str(""), result); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
Reg addr = visit(expr);
|
||||
emit("save to var " + expr.getText(), OpCode.store, result, addr); //$NON-NLS-1$
|
||||
});
|
||||
} else if (SimpleType.CHAR.equals(an.types.get(expr))) {
|
||||
return regPool.withReg((count, result) -> {
|
||||
// Get input until at least 1 character
|
||||
Label getTarget = makeLabel("lcin_l"); //$NON-NLS-1$
|
||||
Label continueTarget = makeLabel("lcin_e"); //$NON-NLS-1$
|
||||
|
||||
emit("", getTarget, OpCode.cin, new Str("")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
emit("str length", OpCode.pop, count); //$NON-NLS-1$
|
||||
emit("repeat if 0 length", OpCode.cbr, count, continueTarget, getTarget); //$NON-NLS-1$
|
||||
|
||||
// Get character
|
||||
emit("pop whole string", continueTarget, OpCode.cpop, result); //$NON-NLS-1$
|
||||
Reg addr = visit(expr);
|
||||
emit("save to var " + expr.getText(), OpCode.cstore, result, addr); //$NON-NLS-1$
|
||||
|
||||
// Pop all remaining characters
|
||||
Label loopTarget = makeLabel("lcpop_l"); //$NON-NLS-1$
|
||||
Label iterTarget = makeLabel("lcpop_c"); //$NON-NLS-1$
|
||||
Label stopTarget = makeLabel("lcpop_e"); //$NON-NLS-1$
|
||||
regPool.withReg((temp) -> {
|
||||
emit("pop remaining", loopTarget, OpCode.subI, count, new Num(1), count); //$NON-NLS-1$
|
||||
emit("pop remaining", OpCode.cbr, count, iterTarget, stopTarget); //$NON-NLS-1$
|
||||
emit("pop remaining", iterTarget, OpCode.cpop, temp); //$NON-NLS-1$
|
||||
emit("pop remaining", OpCode.jumpI, loopTarget); //$NON-NLS-1$
|
||||
emit("pop remaining", stopTarget, OpCode.nop); //$NON-NLS-1$
|
||||
});
|
||||
});
|
||||
} else {
|
||||
emit("reading unknown type", OpCode.haltI, new Num(0x72656164)); //$NON-NLS-1$
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1010,14 +961,20 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
|||
|
||||
@Override
|
||||
public Reg visitWrite(WriteContext ctx) {
|
||||
if (ctx.expr().size() > 1) {
|
||||
for (ExprContext expr : ctx.expr()) {
|
||||
Reg result = visit(expr);
|
||||
|
||||
regPool.blockReg(result, () -> {
|
||||
Type type = an.types.get(expr);
|
||||
|
||||
if (SimpleType.BOOL.equals(type) || SimpleType.INT.equals(type)) {
|
||||
if (SimpleType.BOOL.equals(type)) {
|
||||
regPool.withReg((temp) -> {
|
||||
emit("call stdbout", OpCode.loadI, new Num(prog.size() + 4), temp); // $NON-NLS-2$ //$NON-NLS-1$
|
||||
emit("call stdbout", OpCode.push, temp); //$NON-NLS-1$
|
||||
emit("call stdbout", OpCode.push, result); //$NON-NLS-1$
|
||||
emit("call stdbout", OpCode.jumpI, new Label("stdbout")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
});
|
||||
} else if (SimpleType.INT.equals(type)) {
|
||||
emit("", OpCode.out, new Str(""), result); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} else if (SimpleType.CHAR.equals(type)) {
|
||||
regPool.withReg((temp) -> {
|
||||
|
@ -1034,31 +991,11 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
|||
if (type instanceof ReferenceType)
|
||||
decrementReference(type, result);
|
||||
});
|
||||
|
||||
if (ctx.expr().size() == 1)
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
ExprContext expr = ctx.expr(0);
|
||||
Reg result = visit(expr);
|
||||
|
||||
return regPool.blockReg(result, () -> {
|
||||
Type type = an.types.get(expr);
|
||||
|
||||
if (SimpleType.BOOL.equals(type) || SimpleType.INT.equals(type)) {
|
||||
emit("", OpCode.out, new Str(""), result); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return result;
|
||||
} else if (SimpleType.CHAR.equals(type)) {
|
||||
regPool.withReg((temp) -> {
|
||||
emit("push character", OpCode.cpush, result); //$NON-NLS-1$
|
||||
emit("load 1", OpCode.loadI, new Num(1), temp); //$NON-NLS-1$
|
||||
emit("push 1", OpCode.push, temp); //$NON-NLS-1$
|
||||
emit("print character", OpCode.cout, new Str("")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
});
|
||||
return result;
|
||||
} else {
|
||||
emit("writing unknown type", OpCode.haltI, new Num(0x77726974)); //$NON-NLS-1$
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ memlib_: loadI 0 => m_0
|
|||
// allocate memory
|
||||
// searches through the free slots for either a slot size of ~~exactly #4+8 or a size of~~ at
|
||||
// least #4+16
|
||||
// memory: [return address, object size] -> [object address]
|
||||
// stack: [return address, object size] -> [object address]
|
||||
memalloc: loadI 0 => m_0
|
||||
pop => m_s // load size
|
||||
loadI @fst_ptr => m_p // load previous address (base pointer)
|
||||
|
@ -77,7 +77,7 @@ ma_null: pop => m_1 // load return address
|
|||
|
||||
|
||||
// increase reference count of object
|
||||
// memory: [return address, object address] -> []
|
||||
// stack: [return address, object address] -> []
|
||||
memaddref: loadI 0 => m_0
|
||||
pop => m_n // load object address
|
||||
cmp_EQ m_0,m_n => m_1
|
||||
|
@ -92,7 +92,7 @@ mr_nnul: loadAI m_n,@off_oref => m_1
|
|||
|
||||
// decrease reference count of object
|
||||
// frees memory if count goes to zero
|
||||
// memory: [return address, object address] -> []
|
||||
// stack: [return address, object address] -> []
|
||||
memfree: loadI 0 => m_0
|
||||
pop => m_n // load object address
|
||||
cmp_EQ m_0,m_n => m_1
|
||||
|
@ -111,8 +111,8 @@ mf_free: subI m_n,@header => m_n
|
|||
loadI @fst_ptr => m_p
|
||||
loadAI m_p,@off_next => m_c
|
||||
|
||||
mf_loop: cmp_EQ m_0,m_c => m_1 // check if address pointer is null
|
||||
cbr m_1 -> mf_halt,mf_cont
|
||||
mf_loop: cmp_EQ m_0,m_c => m_1 // loop until the surrounding free blocks are found
|
||||
cbr m_1 -> mf_halt,mf_cont // check if address pointer is null
|
||||
mf_halt: haltI 1882220141 // halt program; object beyond last free slot (or memory corrupted)
|
||||
mf_cont: cmp_EQ m_c,m_n => m_1
|
||||
cbr m_1 -> mf_hal2,mf_con2
|
||||
|
@ -152,7 +152,7 @@ mf_nnxt: storeAI m_c => m_n,@off_next // link new free slot with next
|
|||
|
||||
|
||||
// copy object to location
|
||||
// memory: [return address, object address, destination] -> []
|
||||
// stack: [return address, object address, destination] -> []
|
||||
memcopy: loadI 0 => m_0
|
||||
haltI 1835626101 // unimplemented
|
||||
pop => m_1 // load return address
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// stdlib - generic subroutines for ILOC
|
||||
//
|
||||
// This library contains a few common subroutines for Boppi.
|
||||
//
|
||||
// @author Frank Wibbelink
|
||||
|
||||
// initialise
|
||||
stdlib_: jumpI -> estdlib_
|
||||
|
||||
// write a boolean to output
|
||||
// stack: [return address, bool] -> []
|
||||
stdbout: pop => m_1 // get boolean
|
||||
loadI 0 => m_2 // load zero-length string
|
||||
push m_2
|
||||
cbr m_1 -> sbout_t,sbout_f
|
||||
sbout_t: cout "true"
|
||||
jumpI -> sbout_e
|
||||
sbout_f: cout "false"
|
||||
sbout_e: pop => m_1 // load return address
|
||||
jump -> m_1
|
||||
|
||||
|
||||
// read a character from input
|
||||
// stack: [return address] -> [char]
|
||||
stdcin: cin "" // get line
|
||||
pop => m_1 // get length
|
||||
cbr m_1 -> scin_t,stdcin // repeat until at least one character
|
||||
scin_t: cpop => m_2 // save character
|
||||
scin_lc: subI m_1, 1 => m_1 // decrement char count
|
||||
cbr m_1 -> scin_ll,scin_le
|
||||
scin_ll: cpop => m_0 // discard character
|
||||
jumpI -> scin_lc // repeat
|
||||
scin_le: loadI 0 => m_0 // reset zero register
|
||||
pop => m_1 // get return address
|
||||
cpush m_2 // push result character
|
||||
jump -> m_1
|
||||
|
||||
estdlib_: nop
|
||||
// end of stdlib
|
Loading…
Reference in New Issue