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 {
|
try {
|
||||||
String memlib = new String(Files.readAllBytes(ToolChain.PATH.resolve("memlib.iloc"))); //$NON-NLS-1$
|
String memlib = new String(Files.readAllBytes(ToolChain.PATH.resolve("memlib.iloc"))); //$NON-NLS-1$
|
||||||
prog = Assembler.instance().assemble(memlib);
|
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) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -823,88 +832,30 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Reg visitRead(ReadContext ctx) {
|
public Reg visitRead(ReadContext ctx) {
|
||||||
if (ctx.variable().size() > 1) {
|
Reg res = null;
|
||||||
for (VariableContext expr : ctx.variable()) {
|
for (VariableContext expr : ctx.variable()) {
|
||||||
visit(expr);
|
visit(expr);
|
||||||
|
|
||||||
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) {
|
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr)))
|
||||||
regPool.withReg((temp) -> {
|
res = regPool.withReg((temp) -> {
|
||||||
emit("", OpCode.in, new Str(""), temp); //$NON-NLS-1$ //$NON-NLS-2$
|
emit("", OpCode.in, new Str(""), temp); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
Reg addr = visit(expr);
|
Reg addr = visit(expr);
|
||||||
emit("save to var " + expr.getText(), OpCode.store, temp, addr); //$NON-NLS-1$
|
emit("save to var " + expr.getText(), OpCode.store, temp, addr); //$NON-NLS-1$
|
||||||
});
|
});
|
||||||
} else if (SimpleType.CHAR.equals(an.types.get(expr))) {
|
else if (SimpleType.CHAR.equals(an.types.get(expr)))
|
||||||
// Get input until at least 1 character
|
res = regPool.withReg((temp) -> {
|
||||||
Label getTarget = makeLabel("lcin_l"); //$NON-NLS-1$
|
emit("call stdcin", OpCode.loadI, new Num(prog.size() + 3), temp); //$NON-NLS-1$
|
||||||
Label continueTarget = makeLabel("lcin_e"); //$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$
|
||||||
regPool.withReg((temp, count) -> {
|
emit("get character", OpCode.cpop, temp); //$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, temp); //$NON-NLS-1$
|
|
||||||
Reg addr = visit(expr);
|
Reg addr = visit(expr);
|
||||||
emit("save to var " + expr.getText(), OpCode.cstore, temp, addr); //$NON-NLS-1$
|
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$
|
emit("reading unknown type", OpCode.haltI, new Num(0x72656164)); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return res;
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1010,14 +961,20 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Reg visitWrite(WriteContext ctx) {
|
public Reg visitWrite(WriteContext ctx) {
|
||||||
if (ctx.expr().size() > 1) {
|
|
||||||
for (ExprContext expr : ctx.expr()) {
|
for (ExprContext expr : ctx.expr()) {
|
||||||
Reg result = visit(expr);
|
Reg result = visit(expr);
|
||||||
|
|
||||||
regPool.blockReg(result, () -> {
|
regPool.blockReg(result, () -> {
|
||||||
Type type = an.types.get(expr);
|
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$
|
emit("", OpCode.out, new Str(""), result); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
} else if (SimpleType.CHAR.equals(type)) {
|
} else if (SimpleType.CHAR.equals(type)) {
|
||||||
regPool.withReg((temp) -> {
|
regPool.withReg((temp) -> {
|
||||||
|
@ -1034,31 +991,11 @@ public class BoppiGenerator extends BoppiBaseVisitor<Reg> {
|
||||||
if (type instanceof ReferenceType)
|
if (type instanceof ReferenceType)
|
||||||
decrementReference(type, result);
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ memlib_: loadI 0 => m_0
|
||||||
// allocate memory
|
// allocate memory
|
||||||
// searches through the free slots for either a slot size of ~~exactly #4+8 or a size of~~ at
|
// searches through the free slots for either a slot size of ~~exactly #4+8 or a size of~~ at
|
||||||
// least #4+16
|
// least #4+16
|
||||||
// memory: [return address, object size] -> [object address]
|
// stack: [return address, object size] -> [object address]
|
||||||
memalloc: loadI 0 => m_0
|
memalloc: loadI 0 => m_0
|
||||||
pop => m_s // load size
|
pop => m_s // load size
|
||||||
loadI @fst_ptr => m_p // load previous address (base pointer)
|
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
|
// increase reference count of object
|
||||||
// memory: [return address, object address] -> []
|
// stack: [return address, object address] -> []
|
||||||
memaddref: loadI 0 => m_0
|
memaddref: loadI 0 => m_0
|
||||||
pop => m_n // load object address
|
pop => m_n // load object address
|
||||||
cmp_EQ m_0,m_n => m_1
|
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
|
// decrease reference count of object
|
||||||
// frees memory if count goes to zero
|
// frees memory if count goes to zero
|
||||||
// memory: [return address, object address] -> []
|
// stack: [return address, object address] -> []
|
||||||
memfree: loadI 0 => m_0
|
memfree: loadI 0 => m_0
|
||||||
pop => m_n // load object address
|
pop => m_n // load object address
|
||||||
cmp_EQ m_0,m_n => m_1
|
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
|
loadI @fst_ptr => m_p
|
||||||
loadAI m_p,@off_next => m_c
|
loadAI m_p,@off_next => m_c
|
||||||
|
|
||||||
mf_loop: cmp_EQ m_0,m_c => m_1 // check if address pointer is null
|
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
|
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_halt: haltI 1882220141 // halt program; object beyond last free slot (or memory corrupted)
|
||||||
mf_cont: cmp_EQ m_c,m_n => m_1
|
mf_cont: cmp_EQ m_c,m_n => m_1
|
||||||
cbr m_1 -> mf_hal2,mf_con2
|
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
|
// copy object to location
|
||||||
// memory: [return address, object address, destination] -> []
|
// stack: [return address, object address, destination] -> []
|
||||||
memcopy: loadI 0 => m_0
|
memcopy: loadI 0 => m_0
|
||||||
haltI 1835626101 // unimplemented
|
haltI 1835626101 // unimplemented
|
||||||
pop => m_1 // load return address
|
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