added memory allocator with tests
This commit is contained in:
parent
b617136564
commit
87b859a70c
|
@ -167,7 +167,8 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
|||
|
||||
@Override
|
||||
public Type visitExpr(ExprContext ctx) {
|
||||
if (ctx.singleExpr(ctx.singleExpr().size() - 1) instanceof DeclareContext)
|
||||
ParserRuleContext lastExpr = ctx.singleExpr(ctx.singleExpr().size() - 1);
|
||||
if (lastExpr instanceof DeclareContext || lastExpr instanceof DeclareFunctionContext)
|
||||
log.severe(getError(ctx, "Compound expression ends with declaration."));
|
||||
|
||||
return ctx.singleExpr().stream().map(this::visit).reduce((__, snd) -> snd).get();
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
fst_ptr <- 28
|
||||
slot1 <- 32
|
||||
header <- 8
|
||||
off_oref <- -8
|
||||
off_osize <- -4
|
||||
off_next <- 0
|
||||
off_size <- 4
|
||||
|
||||
// memlib - simple memory allocator for ILOC
|
||||
//
|
||||
// This library maintains a single-linked list (of monotonically increasing addresses) of free
|
||||
// slots in memory and a reference count for occupied slots. Each slot contains a tuple `(next
|
||||
// free slot address,size)` followed by `size` free bytes. The memory is initiliased with a
|
||||
// pointer to the first free slot at `#fst_ptr` and one free slot at `#slot1` of size
|
||||
// `brk-slot1-header`. When a piece of memory is requested for allocation, a tuple
|
||||
// `(reference count, size)` followed by `size` bytes for the object is formed. The calling
|
||||
// convention of the functions in this library consists of storing the return address at #0,
|
||||
// arguments at #4, #8 and #12 and return values (if any) at #16, #20 and #24.
|
||||
//
|
||||
// Requires a register `brk` for the highest address available for heap allocation.
|
||||
// Requires an instruction `halt` when memory runs out
|
||||
//
|
||||
// @author Frank Wibbelink
|
||||
|
||||
// initialise
|
||||
memlib_: loadI 0 => m_0
|
||||
loadI @slot1 => m_1
|
||||
subI brk,@slot1 => m_2
|
||||
subI m_2,@header => m_2
|
||||
storeAI m_1 => m_0,@fst_ptr // pointer to first slot
|
||||
storeAI m_0 => m_1,@off_next // next slot is null
|
||||
storeAI m_2 => m_1,@off_size // first slot size
|
||||
jumpI -> ememlib_
|
||||
|
||||
|
||||
// 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]
|
||||
memalloc: loadI 0 => m_0
|
||||
loadAI m_0,4 => m_s // load size from #4
|
||||
loadI @fst_ptr => m_p // load previous address (base pointer)
|
||||
loadAI m_p,@off_next => m_c // load current address (first slot)
|
||||
|
||||
ma_loop: cmp_EQ m_0,m_c => m_1 // check if address pointer is null
|
||||
cbr m_1 -> ma_null,ma_cont // if null, go to end and return null pointer
|
||||
ma_cont: loadAI m_c,@off_size => m_1 // load slot size
|
||||
cmp_EQ m_1,m_s => m_2 // check if request fits exactly
|
||||
cbr m_2 -> ma_yxct,ma_nxct
|
||||
ma_nxct: subI m_1,@header => m_1 // subtract free slot size
|
||||
cmp_GE m_1,m_s => m_1 // check if request fits
|
||||
cbr m_1 -> ma_found,ma_next
|
||||
ma_next: i2i m_c => m_p
|
||||
loadAI m_p,@off_next => m_c
|
||||
jumpI -> ma_loop
|
||||
|
||||
ma_yxct: loadAI m_c,@off_next => m_n // location of next free slot
|
||||
jumpI -> ma_final
|
||||
|
||||
ma_found: addI m_s,@header => m_1
|
||||
add m_1,m_c => m_n // location of new free slot
|
||||
loadAI m_c,@off_size => m_1
|
||||
subI m_1,@header => m_1
|
||||
sub m_1,m_s => m_1 // size of new free slot
|
||||
storeAI m_1 => m_n,@off_size
|
||||
loadAI m_c,@off_next => m_1 // location of next free slot
|
||||
storeAI m_1 => m_n,@off_next
|
||||
ma_final: storeAI m_n => m_p,@off_next // link previous free slot to new
|
||||
addI m_c,@header => m_c // move to object location
|
||||
loadI 1 => m_1
|
||||
storeAI m_1 => m_c,@off_oref // set reference count to 1
|
||||
storeAI m_s => m_c,@off_osize // set object size
|
||||
ma_null: storeAI m_c => m_0,16 // store object address at #16
|
||||
loadAI m_0,0 => m_r // load return address from #0
|
||||
jump -> m_r
|
||||
|
||||
|
||||
// increase reference count of object
|
||||
// memory: [return address, object address] -> []
|
||||
memaddref: loadI 0 => m_0
|
||||
loadAI m_0,4 => m_n // load object address from #4
|
||||
cmp_EQ m_0,m_n => m_1
|
||||
cbr m_1 -> mr_ynul,mr_nnul // check if null pointer
|
||||
mr_ynul: haltI 1865445997
|
||||
mr_nnul: loadAI m_n,@off_oref => m_1
|
||||
addI m_1,1 => m_1
|
||||
storeAI m_1 => m_n,@off_oref
|
||||
loadAI m_0,0 => m_r // load return address from #0
|
||||
jump -> m_r
|
||||
|
||||
|
||||
// decrease reference count of object
|
||||
// frees memory if count goes to zero
|
||||
// memory: [return address, object address] -> []
|
||||
memfree: loadI 0 => m_0
|
||||
loadAI m_0,4 => m_n // load object from #4
|
||||
cmp_EQ m_0,m_n => m_1
|
||||
cbr m_1 -> mf_ynul,mf_nnul // check if null pointer
|
||||
mf_ynul: haltI 1865442925
|
||||
mf_nnul: loadAI m_n,@off_oref => m_1
|
||||
subI m_1,1 => m_1
|
||||
cmp_GT m_1,m_0 => m_1
|
||||
cbr m_1 -> mf_exit,mf_free
|
||||
|
||||
mf_exit: storeAI m_1 => m_n,@off_oref
|
||||
loadAI m_0,0 => m_r // load return address from #0
|
||||
jump -> m_r
|
||||
|
||||
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_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
|
||||
mf_hal2: haltI 1717855853 // halt program; object is free slot
|
||||
mf_con2: cmp_LE m_c,m_n => m_1
|
||||
cbr m_1 -> mf_next, mf_done
|
||||
mf_next: i2i m_c => m_p
|
||||
loadAI m_p,@off_next => m_c
|
||||
jumpI -> mf_loop
|
||||
|
||||
mf_done: loadAI m_p,@off_size => m_1
|
||||
addI m_1,@header => m_1
|
||||
add m_1,m_p => m_2
|
||||
cmp_EQ m_2,m_n => m_2
|
||||
cbr m_2 -> mf_yprv,mf_nprv
|
||||
mf_yprv: loadAI m_n,@off_size => m_2 // merge with previous free slot
|
||||
add m_1,m_2 => m_1 // new size of previous free slot
|
||||
storeAI m_1 => m_p,@off_size
|
||||
i2i m_p => m_n
|
||||
jumpI -> mf_dprv
|
||||
mf_nprv: storeAI m_n => m_p,@off_next // link previous free slot with new
|
||||
mf_dprv: loadAI m_n,@off_size => m_1
|
||||
addI m_1,@header => m_1
|
||||
add m_1,m_n => m_2
|
||||
cmp_EQ m_2,m_c => m_2
|
||||
cbr m_2 -> mf_ynxt,mf_nnxt
|
||||
mf_ynxt: loadAI m_c,@off_size => m_2 // merge with next free slot
|
||||
add m_1,m_2 => m_1 // new size of next free slot
|
||||
storeAI m_1 => m_n,@off_size
|
||||
loadAI m_c,@off_next => m_1
|
||||
storeAI m_1 => m_n,@off_next // move link of next's next to new free slot
|
||||
jumpI -> mf_exit
|
||||
mf_nnxt: storeAI m_c => m_n,@off_next // link new free slot with next
|
||||
loadAI m_0,0 => m_r // load return address from #0
|
||||
jump -> m_r
|
||||
|
||||
|
||||
// copy object to location
|
||||
// memory: [return address, object address, destination] -> []
|
||||
memcopy: loadI 0 => m_0
|
||||
haltI 1835626101 // unimplemented
|
||||
loadAI m_0,0 => m_r // load return address from #0
|
||||
jump -> m_r
|
||||
|
||||
|
||||
ememlib_: nop
|
||||
// end of memlib
|
||||
|
|
@ -1,191 +1,16 @@
|
|||
package pp.s1184725.boppi.test;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.util.List;
|
||||
import java.util.logging.*;
|
||||
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
import pp.iloc.Simulator;
|
||||
import pp.iloc.model.Program;
|
||||
import pp.s1184725.boppi.*;
|
||||
|
||||
/**
|
||||
* Test suite for all Boppi language features. This suite contains helper
|
||||
* functions and attributes to assist test cases. Each test case should consider
|
||||
* a single language feature across all compiler stages.
|
||||
* Test suite for all tests, including the Boppi language and utilities.
|
||||
*
|
||||
* @author Frank Wibbelink
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({ ExpressionTest.class, SimpleVariableTest.class, ConditionalTest.class, SimpleFunctionTest.class })
|
||||
@SuiteClasses({ BoppiTests.class, ILOCAllocatorTest.class })
|
||||
public class AllTests {
|
||||
/**
|
||||
* The path for test programs
|
||||
*/
|
||||
public static final Path TEST_PROGRAM_LOCATION = Paths
|
||||
.get("src/" + AllTests.class.getPackage().getName().replaceAll("\\.", "/") + "/programs/");
|
||||
|
||||
/**
|
||||
* The default logging level
|
||||
*/
|
||||
public static final Level DEFAULT_LOG_LEVEL = Level.SEVERE;
|
||||
|
||||
/**
|
||||
* Log records of last test
|
||||
*/
|
||||
public static List<LogRecord> log;
|
||||
|
||||
/**
|
||||
* Output of last program split by line breaks
|
||||
*/
|
||||
public static String[] out;
|
||||
|
||||
/**
|
||||
* The level of error reporting to use for the tests. Can be changed to
|
||||
* include finer tests.
|
||||
*/
|
||||
private static Level logLevel = DEFAULT_LOG_LEVEL;
|
||||
|
||||
/**
|
||||
* Runs a test with warnings enabled.
|
||||
*
|
||||
* @param test
|
||||
* the test to run
|
||||
*/
|
||||
public static void withWarnings(Runnable test) {
|
||||
logLevel = Level.WARNING;
|
||||
test.run();
|
||||
logLevel = DEFAULT_LOG_LEVEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string of code, logging to {@link #log}.
|
||||
*
|
||||
* @param code
|
||||
* the code to parse
|
||||
*/
|
||||
public static void parseString(String code) {
|
||||
parse(ToolChain.getCharStream(code));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses code from a file, logging to {@link #log}.
|
||||
*
|
||||
* @param file
|
||||
* the file name
|
||||
*/
|
||||
public static void parseFile(String file) {
|
||||
parse(ToolChain.getCharStream(TEST_PROGRAM_LOCATION.resolve(file)));
|
||||
}
|
||||
|
||||
private static void parse(CharStream stream) {
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(logLevel);
|
||||
|
||||
ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and type checks a string of code, logging to {@link #log}.
|
||||
*
|
||||
* @param code
|
||||
* the code to type check
|
||||
*/
|
||||
public static void checkString(String code) {
|
||||
check(ToolChain.getCharStream(code));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and type checks code from a file, logging to {@link #log}.
|
||||
*
|
||||
* @param file
|
||||
* the file name
|
||||
*/
|
||||
public static void checkFile(String file) {
|
||||
check(ToolChain.getCharStream(TEST_PROGRAM_LOCATION.resolve(file)));
|
||||
}
|
||||
|
||||
private static void check(CharStream stream) {
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(logLevel);
|
||||
|
||||
ToolChain.getAnnotations(ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program(), logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles and runs a program from a string, logging to {@link #log} and
|
||||
* writing lines of output to {@link #out}.
|
||||
*
|
||||
* @param code
|
||||
* the code to type check
|
||||
* @param input
|
||||
* lines of input for the program
|
||||
*/
|
||||
public static void compileAndRunString(String code, String... input) {
|
||||
compileAndRun(ToolChain.getCharStream(code), String.join("\n", input) + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles and runs a program from a file, logging to {@link #log} and
|
||||
* writing lines of output to {@link #out}.
|
||||
*
|
||||
* @param file
|
||||
* the file name
|
||||
* @param input
|
||||
* lines of input for the program
|
||||
*/
|
||||
public static void compileAndRunFile(String file, String... input) {
|
||||
compileAndRun(ToolChain.getCharStream(TEST_PROGRAM_LOCATION.resolve(file)), String.join("\n", input) + "\n");
|
||||
}
|
||||
|
||||
private static void compileAndRun(CharStream stream, String input) {
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(logLevel);
|
||||
|
||||
ParseTree ast = ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program();
|
||||
Annotations annotations = ToolChain.getAnnotations(ast, logger);
|
||||
Program program = ToolChain.getILOC(ast, logger, annotations);
|
||||
|
||||
if (Simulator.DEBUG)
|
||||
System.out.println(program.prettyPrint());
|
||||
|
||||
out = ToolChain.execute(program, logger, input).split("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles and runs a program in debug mode, printing the generated
|
||||
* program, a simulation of the program and all log messages.
|
||||
*
|
||||
* @param stream
|
||||
* a character stream with the program code
|
||||
* @param input
|
||||
* lines of input for the program
|
||||
*/
|
||||
public static void debugRun(CharStream stream, String... input) {
|
||||
Simulator.DEBUG = true;
|
||||
String in = String.join("\n", input) + "\n";
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(Level.FINEST);
|
||||
|
||||
ParseTree ast = ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program();
|
||||
Annotations annotations = ToolChain.getAnnotations(ast, logger);
|
||||
Program program = ToolChain.getILOC(ast, logger, annotations);
|
||||
|
||||
System.out.println(program.prettyPrint());
|
||||
|
||||
out = ToolChain.execute(program, logger, in).split("\n");
|
||||
|
||||
log.forEach((entry) -> System.out.println(entry.getMessage()));
|
||||
Simulator.DEBUG = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
package pp.s1184725.boppi.test;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.util.List;
|
||||
import java.util.logging.*;
|
||||
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
import pp.iloc.Simulator;
|
||||
import pp.iloc.model.Program;
|
||||
import pp.s1184725.boppi.*;
|
||||
|
||||
/**
|
||||
* Test suite for all Boppi language features. This suite contains helper
|
||||
* functions and attributes to assist test cases. Each test case should consider
|
||||
* a single language feature across all compiler stages.
|
||||
*
|
||||
* @author Frank Wibbelink
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({ ExpressionTest.class, SimpleVariableTest.class, ConditionalTest.class, SimpleFunctionTest.class })
|
||||
public class BoppiTests {
|
||||
/**
|
||||
* The path for test programs
|
||||
*/
|
||||
public static final Path TEST_PROGRAM_LOCATION = Paths
|
||||
.get("src/" + BoppiTests.class.getPackage().getName().replaceAll("\\.", "/") + "/programs/");
|
||||
|
||||
/**
|
||||
* The default logging level
|
||||
*/
|
||||
public static final Level DEFAULT_LOG_LEVEL = Level.SEVERE;
|
||||
|
||||
/**
|
||||
* Log records of last test
|
||||
*/
|
||||
public static List<LogRecord> log;
|
||||
|
||||
/**
|
||||
* Output of last program split by line breaks
|
||||
*/
|
||||
public static String[] out;
|
||||
|
||||
/**
|
||||
* The level of error reporting to use for the tests. Can be changed to
|
||||
* include finer tests.
|
||||
*/
|
||||
private static Level logLevel = DEFAULT_LOG_LEVEL;
|
||||
|
||||
/**
|
||||
* Runs a test with warnings enabled.
|
||||
*
|
||||
* @param test
|
||||
* the test to run
|
||||
*/
|
||||
public static void withWarnings(Runnable test) {
|
||||
logLevel = Level.WARNING;
|
||||
test.run();
|
||||
logLevel = DEFAULT_LOG_LEVEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string of code, logging to {@link #log}.
|
||||
*
|
||||
* @param code
|
||||
* the code to parse
|
||||
*/
|
||||
public static void parseString(String code) {
|
||||
parse(ToolChain.getCharStream(code));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses code from a file, logging to {@link #log}.
|
||||
*
|
||||
* @param file
|
||||
* the file name
|
||||
*/
|
||||
public static void parseFile(String file) {
|
||||
parse(ToolChain.getCharStream(TEST_PROGRAM_LOCATION.resolve(file)));
|
||||
}
|
||||
|
||||
private static void parse(CharStream stream) {
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(logLevel);
|
||||
|
||||
ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and type checks a string of code, logging to {@link #log}.
|
||||
*
|
||||
* @param code
|
||||
* the code to type check
|
||||
*/
|
||||
public static void checkString(String code) {
|
||||
check(ToolChain.getCharStream(code));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and type checks code from a file, logging to {@link #log}.
|
||||
*
|
||||
* @param file
|
||||
* the file name
|
||||
*/
|
||||
public static void checkFile(String file) {
|
||||
check(ToolChain.getCharStream(TEST_PROGRAM_LOCATION.resolve(file)));
|
||||
}
|
||||
|
||||
private static void check(CharStream stream) {
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(logLevel);
|
||||
|
||||
ToolChain.getAnnotations(ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program(), logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles and runs a program from a string, logging to {@link #log} and
|
||||
* writing lines of output to {@link #out}.
|
||||
*
|
||||
* @param code
|
||||
* the code to type check
|
||||
* @param input
|
||||
* lines of input for the program
|
||||
*/
|
||||
public static void compileAndRunString(String code, String... input) {
|
||||
compileAndRun(ToolChain.getCharStream(code), String.join("\n", input) + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles and runs a program from a file, logging to {@link #log} and
|
||||
* writing lines of output to {@link #out}.
|
||||
*
|
||||
* @param file
|
||||
* the file name
|
||||
* @param input
|
||||
* lines of input for the program
|
||||
*/
|
||||
public static void compileAndRunFile(String file, String... input) {
|
||||
compileAndRun(ToolChain.getCharStream(TEST_PROGRAM_LOCATION.resolve(file)), String.join("\n", input) + "\n");
|
||||
}
|
||||
|
||||
private static void compileAndRun(CharStream stream, String input) {
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(logLevel);
|
||||
|
||||
ParseTree ast = ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program();
|
||||
Annotations annotations = ToolChain.getAnnotations(ast, logger);
|
||||
Program program = ToolChain.getILOC(ast, logger, annotations);
|
||||
|
||||
if (Simulator.DEBUG)
|
||||
System.out.println(program.prettyPrint());
|
||||
|
||||
out = ToolChain.execute(program, logger, input).split("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles and runs a program in debug mode, printing the generated
|
||||
* program, a simulation of the program and all log messages.
|
||||
*
|
||||
* @param stream
|
||||
* a character stream with the program code
|
||||
* @param input
|
||||
* lines of input for the program
|
||||
*/
|
||||
public static void debugRun(CharStream stream, String... input) {
|
||||
Simulator.DEBUG = true;
|
||||
String in = String.join("\n", input) + "\n";
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(Level.FINEST);
|
||||
|
||||
ParseTree ast = ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program();
|
||||
Annotations annotations = ToolChain.getAnnotations(ast, logger);
|
||||
Program program = ToolChain.getILOC(ast, logger, annotations);
|
||||
|
||||
System.out.println(program.prettyPrint());
|
||||
|
||||
out = ToolChain.execute(program, logger, in).split("\n");
|
||||
|
||||
log.forEach((entry) -> System.out.println(entry.getMessage()));
|
||||
Simulator.DEBUG = false;
|
||||
}
|
||||
|
||||
}
|
|
@ -16,11 +16,11 @@ public class ConditionalTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctConditionalParsing() {
|
||||
AllTests.parseFile("if.boppi");
|
||||
assertThat(AllTests.log, empty());
|
||||
BoppiTests.parseFile("if.boppi");
|
||||
assertThat(BoppiTests.log, empty());
|
||||
|
||||
AllTests.parseFile("while.boppi");
|
||||
assertThat(AllTests.log, empty());
|
||||
BoppiTests.parseFile("while.boppi");
|
||||
assertThat(BoppiTests.log, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,11 +28,11 @@ public class ConditionalTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctConditionalChecking() {
|
||||
AllTests.checkFile("if.boppi");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.checkFile("if.boppi");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.checkFile("while.boppi");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.checkFile("while.boppi");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,29 +40,29 @@ public class ConditionalTest {
|
|||
*/
|
||||
@Test
|
||||
public void basicPrograms() {
|
||||
AllTests.compileAndRunString("print(5*3)");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
assertThat(AllTests.out, is(arrayContaining("15")));
|
||||
BoppiTests.compileAndRunString("print(5*3)");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
assertThat(BoppiTests.out, is(arrayContaining("15")));
|
||||
|
||||
AllTests.compileAndRunString("print({var int x; x := 8; print(x)})");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
assertThat(AllTests.out, is(arrayContaining("8", "8")));
|
||||
BoppiTests.compileAndRunString("print({var int x; x := 8; print(x)})");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
assertThat(BoppiTests.out, is(arrayContaining("8", "8")));
|
||||
|
||||
AllTests.compileAndRunString("print('T', 'e', 's', 't', '!')");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
assertThat(AllTests.out, is(arrayContaining("T", "e", "s", "t", "!")));
|
||||
BoppiTests.compileAndRunString("print('T', 'e', 's', 't', '!')");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
assertThat(BoppiTests.out, is(arrayContaining("T", "e", "s", "t", "!")));
|
||||
|
||||
AllTests.compileAndRunString("var int x; var int y; x := 3*(y := 4); print(x,y)");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
assertThat(AllTests.out, is(arrayContaining("12", "4")));
|
||||
BoppiTests.compileAndRunString("var int x; var int y; x := 3*(y := 4); print(x,y)");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
assertThat(BoppiTests.out, is(arrayContaining("12", "4")));
|
||||
|
||||
AllTests.compileAndRunFile("basicProgram1.boppi", "1", "T");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
assertThat(AllTests.out, is(arrayContaining("T", "T")));
|
||||
BoppiTests.compileAndRunFile("basicProgram1.boppi", "1", "T");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
assertThat(BoppiTests.out, is(arrayContaining("T", "T")));
|
||||
|
||||
AllTests.compileAndRunFile("fibonacciIterative.boppi", "6");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
assertThat(AllTests.out, is(arrayContaining("13")));
|
||||
BoppiTests.compileAndRunFile("fibonacciIterative.boppi", "6");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
assertThat(BoppiTests.out, is(arrayContaining("13")));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ public class ExpressionTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctExpressionParsing() {
|
||||
AllTests.parseFile("simpleExpression.boppi");
|
||||
assertThat(AllTests.log, empty());
|
||||
BoppiTests.parseFile("simpleExpression.boppi");
|
||||
assertThat(BoppiTests.log, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,20 +29,20 @@ public class ExpressionTest {
|
|||
*/
|
||||
@Test
|
||||
public void wrongExpressionParsing() {
|
||||
AllTests.parseString("");
|
||||
assertThat(AllTests.log, not(empty()));
|
||||
BoppiTests.parseString("");
|
||||
assertThat(BoppiTests.log, not(empty()));
|
||||
|
||||
AllTests.parseString("~");
|
||||
assertThat(AllTests.log, not(empty()));
|
||||
BoppiTests.parseString("~");
|
||||
assertThat(BoppiTests.log, not(empty()));
|
||||
|
||||
AllTests.parseString("0A");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.parseString("0A");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.parseString("do");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.parseString("do");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.parseString("true true");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.parseString("true true");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,8 +50,8 @@ public class ExpressionTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctExpressionChecking() {
|
||||
AllTests.checkFile("simpleExpression.boppi");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.checkFile("simpleExpression.boppi");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,20 +59,20 @@ public class ExpressionTest {
|
|||
*/
|
||||
@Test
|
||||
public void wrongExpressionChecking() {
|
||||
AllTests.checkString("+true");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("+true");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("5 || true");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("5 || true");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("6 + 'c'");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("6 + 'c'");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("4 + print(5, 6)");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("4 + print(5, 6)");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("print(print(3, 5))");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("print(print(3, 5))");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,16 +80,16 @@ public class ExpressionTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctExpressionGeneration() {
|
||||
AllTests.compileAndRunFile("simpleExpression.boppi");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.compileAndRunFile("simpleExpression.boppi");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
int n = 12;
|
||||
String expression = StringUtils.repeat("1+(", n) + "1" + StringUtils.repeat(")", n);
|
||||
|
||||
AllTests.withWarnings(() -> {
|
||||
AllTests.compileAndRunString("print(" + expression + ")", "" + n);
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
assertThat(AllTests.log.get(0).getLevel(), is(Level.WARNING));
|
||||
BoppiTests.withWarnings(() -> {
|
||||
BoppiTests.compileAndRunString("print(" + expression + ")", "" + n);
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
assertThat(BoppiTests.log.get(0).getLevel(), is(Level.WARNING));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -98,9 +98,9 @@ public class ExpressionTest {
|
|||
*/
|
||||
@Test
|
||||
public void wrongExpressionGeneration() {
|
||||
AllTests.compileAndRunString("1/0");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
assertThat(AllTests.log.get(0).getMessage(), containsString("zero"));
|
||||
BoppiTests.compileAndRunString("1/0");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
assertThat(BoppiTests.log.get(0).getMessage(), containsString("zero"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
package pp.s1184725.boppi.test;
|
||||
|
||||
import java.nio.file.Files;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import pp.iloc.*;
|
||||
import pp.iloc.eval.Machine;
|
||||
import pp.iloc.model.Program;
|
||||
|
||||
/**
|
||||
* Tests for the ILOC simple allocator (memlib.iloc).
|
||||
*
|
||||
* @author Frank Wibbelink
|
||||
*/
|
||||
public class ILOCAllocatorTest {
|
||||
/**
|
||||
* Default free memory (free slot size must report this value when nothing
|
||||
* is allocated).
|
||||
*/
|
||||
private static final int FREEMEM = 0XFF;
|
||||
private static final int HEADER = 8;
|
||||
private static final int FIRSTPTR = 28;
|
||||
private static final int FIRSTSLOT = 32;
|
||||
private static final int SIZEOFFSET = 4;
|
||||
private static final int REFOFFSET = -8;
|
||||
|
||||
private static final String obj1 = "r_obj1", obj2 = "r_obj2", obj3 = "r_obj3";
|
||||
|
||||
private int returnAddress = 0;
|
||||
private Machine vm;
|
||||
|
||||
private String malloc(int size, String reg) {
|
||||
returnAddress++;
|
||||
String s = "";
|
||||
s += "loadI 0 => r0\n";
|
||||
s += "loadI " + size + " => r1\n";
|
||||
s += "storeAI r1 => r0, 4\n";
|
||||
s += "loadI #end" + returnAddress + " => r2\n";
|
||||
s += "storeAI r2 => r0, 0\n";
|
||||
s += "jumpI -> memalloc\n";
|
||||
s += "end" + returnAddress + ": loadAI r0,16 => " + reg + "\n";
|
||||
if (size >= 4) {
|
||||
s += "loadI " + 0xDADACAFE + " => r2\n";
|
||||
s += "storeAI r2 => " + reg + ",0\n";
|
||||
}
|
||||
s += "\n";
|
||||
return s;
|
||||
}
|
||||
|
||||
private String incRef(String reg) {
|
||||
returnAddress++;
|
||||
String s = "";
|
||||
s += "loadI 0 => r0\n";
|
||||
s += "storeAI " + reg + " => r0, 4\n";
|
||||
s += "loadI #end" + returnAddress + " => r2\n";
|
||||
s += "storeAI r2 => r0, 0\n";
|
||||
s += "jumpI -> memaddref\n";
|
||||
s += "end" + returnAddress + ": nop\n";
|
||||
s += "\n";
|
||||
return s;
|
||||
}
|
||||
|
||||
private String free(String reg) {
|
||||
returnAddress++;
|
||||
String s = "";
|
||||
s += "loadI 0 => r0\n";
|
||||
s += "storeAI " + reg + " => r0, 4\n";
|
||||
s += "loadI #end" + returnAddress + " => r2\n";
|
||||
s += "storeAI r2 => r0, 0\n";
|
||||
s += "jumpI -> memfree\n";
|
||||
s += "end" + returnAddress + ": nop\n";
|
||||
s += "\n";
|
||||
return s;
|
||||
}
|
||||
|
||||
private void sim(String code) {
|
||||
try {
|
||||
String memlib = new String(
|
||||
Files.readAllBytes(BoppiTests.TEST_PROGRAM_LOCATION.resolve("../../memlib.iloc")));
|
||||
Program program = Assembler.instance().assemble(memlib + "\n" + code);
|
||||
vm = new Machine();
|
||||
vm.setSize((FREEMEM + FIRSTSLOT + HEADER) * 2);
|
||||
Simulator sim = new Simulator(program, vm);
|
||||
sim.run();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether memlib correctly compiles and initialises.
|
||||
*/
|
||||
@Test
|
||||
public void compileAndRun() {
|
||||
sim("");
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(FIRSTPTR), is(FIRSTSLOT));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR)), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR) + SIZEOFFSET), is(FREEMEM));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether memlib correctly allocates and deallocates at the end of
|
||||
* used memory Tests whether memlib correctly merges deallocated memory with
|
||||
* the free slot at the end.
|
||||
*/
|
||||
@Test
|
||||
public void simpleMallocFree() {
|
||||
sim(malloc(11, obj1));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(FIRSTPTR), is(not(FIRSTSLOT)));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR)), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR) + SIZEOFFSET), is(FREEMEM - (HEADER + 11)));
|
||||
|
||||
sim(malloc(11, obj1) + malloc(7, obj2));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(FIRSTPTR), is(not(FIRSTSLOT)));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR)), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR) + SIZEOFFSET), is(FREEMEM - (HEADER + 11) - (HEADER + 7)));
|
||||
|
||||
sim(malloc(11, obj1) + free(obj1));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR)), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR) + SIZEOFFSET), is(FREEMEM));
|
||||
|
||||
sim(malloc(11, obj1) + malloc(7, obj2) + free(obj2));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR)), is(0));
|
||||
|
||||
sim(malloc(11, obj1) + malloc(7, obj2) + free(obj2) + free(obj1));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR)), is(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether memlib correctly halts the machine if freeing wrong
|
||||
* addresses or using null pointers.
|
||||
*/
|
||||
@Test
|
||||
public void incorrectTests() {
|
||||
sim(malloc(11, obj1) + free(obj1) + free(obj1));
|
||||
assertThat(vm.getInterrupt(), is(not(0)));
|
||||
|
||||
sim(malloc(11, obj1) + incRef("r0"));
|
||||
assertThat(vm.getInterrupt(), is(not(0)));
|
||||
|
||||
sim(malloc(11, obj1) + free("r0"));
|
||||
assertThat(vm.getInterrupt(), is(not(0)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether memlib correctly allocates and deallocates memory in the
|
||||
* middle of used memory. Tests whether memlib correctly merges deallocated
|
||||
* memory with previous and next slots. Tests whether memlib correctly uses
|
||||
* free slots that are either exactly the requested size or fit at least a
|
||||
* new free slot.
|
||||
*/
|
||||
@Test
|
||||
public void discontinuousMemory() {
|
||||
sim(malloc(11, obj1) + malloc(7, obj2) + free(obj1));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR)), is(not(0)));
|
||||
|
||||
sim(malloc(11, obj1) + malloc(7, obj2) + free(obj1) + free(obj2));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR)), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR) + SIZEOFFSET), is(FREEMEM));
|
||||
|
||||
sim(malloc(11, obj1) + malloc(7, obj2) + free(obj1) + malloc(11, obj3));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR)), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR) + SIZEOFFSET), is(FREEMEM - (HEADER + 11) - (HEADER + 7)));
|
||||
|
||||
sim(malloc(11, obj1) + malloc(7, obj2) + free(obj1) + malloc(10, obj3));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR)), is(not(0)));
|
||||
assertThat(vm.load(vm.load(vm.load(FIRSTPTR)) + SIZEOFFSET),
|
||||
is(FREEMEM - (HEADER + 11) - (HEADER + 7) - (HEADER + 10)));
|
||||
|
||||
sim(malloc(11, obj1) + malloc(7, obj2) + free(obj1) + malloc(1, obj3) + malloc(2, obj1));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(FIRSTPTR), is(not(FIRSTSLOT)));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR)), is(0));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR) + SIZEOFFSET), is(FREEMEM - (HEADER + 1) - (HEADER + 2) - (HEADER + 7)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether memlib correctly tracks reference counts.
|
||||
*/
|
||||
@Test
|
||||
public void referenceCounting() {
|
||||
sim(malloc(11, obj1));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(vm.getReg(obj1) + REFOFFSET), is(1));
|
||||
|
||||
sim(malloc(11, obj1) + incRef(obj1));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(vm.getReg(obj1) + REFOFFSET), is(2));
|
||||
|
||||
sim(malloc(11, obj1) + incRef(obj1) + free(obj1));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(FIRSTPTR), is(not(FIRSTSLOT)));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR) + SIZEOFFSET), is(not(FREEMEM)));
|
||||
|
||||
sim(malloc(11, obj1) + incRef(obj1) + free(obj1) + free(obj1));
|
||||
assertThat(vm.getInterrupt(), is(0));
|
||||
assertThat(vm.load(FIRSTPTR), is(FIRSTSLOT));
|
||||
assertThat(vm.load(vm.load(FIRSTPTR) + SIZEOFFSET), is(FREEMEM));
|
||||
}
|
||||
|
||||
}
|
|
@ -16,23 +16,23 @@ public class SimpleFunctionTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctFunctionParsing() {
|
||||
AllTests.parseString("function int id(int a) a; 1");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.parseString("function int id(int a) a; 1");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.parseString("function int id(int a) a; id(1)");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.parseString("function int id(int a) a; id(1)");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.parseString("var int a; a := 1; function int const() a; const()");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.parseString("var int a; a := 1; function int const() a; const()");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.parseString("function int add(int a, int b) a+b; print(add(4, 5)+1)");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.parseString("function int add(int a, int b) a+b; print(add(4, 5)+1)");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.parseString("function char const(char a, char b) a; print(const('A', 'T'))");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.parseString("function char const(char a, char b) a; print(const('A', 'T'))");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.parseString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.parseString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,14 +40,14 @@ public class SimpleFunctionTest {
|
|||
*/
|
||||
@Test
|
||||
public void wrongFunctionParsing() {
|
||||
AllTests.parseString("function doNothing(int a, char b) a+b; print(add(4, 'T')+1)");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.parseString("function doNothing(int a, char b) a+b; print(add(4, 'T')+1)");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.parseString("function char add(int a, int b);");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.parseString("function char add(int a, int b);");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.parseString("function int add(int a, int b) a+b; add(4,)");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.parseString("function int add(int a, int b) a+b; add(4,)");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,23 +55,23 @@ public class SimpleFunctionTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctFunctionChecking() {
|
||||
AllTests.checkString("function int id(int a) a; 1");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.checkString("function int id(int a) a; 1");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.checkString("function int id(int a) a; id(1); 1");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.checkString("function int id(int a) a; id(1); 1");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.checkString("var int a; function int const() a; 1");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.checkString("var int a; function int const() a; 1");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.checkString("function int add(int a, int b) a+b; print(add(4, 5)+1)");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.checkString("function int add(int a, int b) a+b; print(add(4, 5)+1)");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.checkString("function char const(char a, char b) a; print(const('A', 'T'))");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.checkString("function char const(char a, char b) a; print(const('A', 'T'))");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.checkString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.checkString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}; 0");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,14 +79,14 @@ public class SimpleFunctionTest {
|
|||
*/
|
||||
@Test
|
||||
public void wrongFunctionChecking() {
|
||||
AllTests.checkString("function int add(int a, char b) a+b; print(add(4, 'T')+1)");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("function int add(int a, char b) a+b; print(add(4, 'T')+1)");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("function char add(int a, int b) a+b; print(add(4, 5))");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("function char add(int a, int b) a+b; print(add(4, 5))");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("function int add(int a, int b) a+b; print(add(4, 'T')+1)");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("function int add(int a, int b) a+b; print(add(4, 'T')+1)");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,26 +94,26 @@ public class SimpleFunctionTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctSimpleFunctionGeneration() {
|
||||
AllTests.compileAndRunString("function int id(int a) a; 1");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.compileAndRunString("function int id(int a) a; 1");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.compileAndRunString("function int id(int a) a; id(1); 1");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.compileAndRunString("function int id(int a) a; id(1); 1");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.compileAndRunString("var int a; function int const(int b) a; 1");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.compileAndRunString("var int a; function int const(int b) a; 1");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.compileAndRunString("var int a; a := 1; function int const(int b) a; print(const(4))");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
assertThat(AllTests.out, is(arrayContaining("1")));
|
||||
BoppiTests.compileAndRunString("var int a; a := 1; function int const(int b) a; print(const(4))");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
assertThat(BoppiTests.out, is(arrayContaining("1")));
|
||||
|
||||
AllTests.compileAndRunString("function int add(int a, int b) a+b; print(add(4, 5)+1)");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
assertThat(AllTests.out, is(arrayContaining("10")));
|
||||
BoppiTests.compileAndRunString("function int add(int a, int b) a+b; print(add(4, 5)+1)");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
assertThat(BoppiTests.out, is(arrayContaining("10")));
|
||||
|
||||
AllTests.compileAndRunString("function char const(char a, char b) a; print(const('A', 'T'))");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
assertThat(AllTests.out, is(arrayContaining("A")));
|
||||
BoppiTests.compileAndRunString("function char const(char a, char b) a; print(const('A', 'T'))");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
assertThat(BoppiTests.out, is(arrayContaining("A")));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,16 +122,16 @@ public class SimpleFunctionTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctComplexFunctionGeneration() {
|
||||
AllTests.compileAndRunString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.compileAndRunString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}; 0");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
|
||||
AllTests.compileAndRunFile("recursiveFactorial.boppi", "5");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
assertThat(AllTests.out, is(arrayContaining("120")));
|
||||
BoppiTests.compileAndRunFile("recursiveFactorial.boppi", "5");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
assertThat(BoppiTests.out, is(arrayContaining("120")));
|
||||
|
||||
AllTests.compileAndRunFile("simpleFunctionPassing.boppi");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
assertThat(AllTests.out, is(arrayContaining("40", "104", "1", "2", "8")));
|
||||
BoppiTests.compileAndRunFile("simpleFunctionPassing.boppi");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
assertThat(BoppiTests.out, is(arrayContaining("40", "104", "1", "2", "8")));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ public class SimpleVariableTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctVariableParsing() {
|
||||
AllTests.parseFile("simpleVariable.boppi");
|
||||
assertThat(AllTests.log, empty());
|
||||
BoppiTests.parseFile("simpleVariable.boppi");
|
||||
assertThat(BoppiTests.log, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,17 +25,17 @@ public class SimpleVariableTest {
|
|||
*/
|
||||
@Test
|
||||
public void wrongVariableParsing() {
|
||||
AllTests.parseString("var");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.parseString("var");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.parseString("var bool 5");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.parseString("var bool 5");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.parseString("var 'c' varname");
|
||||
assertThat(AllTests.log, not(empty()));
|
||||
BoppiTests.parseString("var 'c' varname");
|
||||
assertThat(BoppiTests.log, not(empty()));
|
||||
|
||||
AllTests.parseString("var bool; true true;");
|
||||
assertThat(AllTests.log, hasSize(2));
|
||||
BoppiTests.parseString("var bool; true true;");
|
||||
assertThat(BoppiTests.log, hasSize(2));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,8 +43,8 @@ public class SimpleVariableTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctScopeParsing() {
|
||||
AllTests.parseFile("simpleScope.boppi");
|
||||
assertThat(AllTests.log, empty());
|
||||
BoppiTests.parseFile("simpleScope.boppi");
|
||||
assertThat(BoppiTests.log, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,8 +52,8 @@ public class SimpleVariableTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctVariableChecking() {
|
||||
AllTests.checkFile("simpleVariable.boppi");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.checkFile("simpleVariable.boppi");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,20 +61,20 @@ public class SimpleVariableTest {
|
|||
*/
|
||||
@Test
|
||||
public void wrongVariableChecking() {
|
||||
AllTests.checkString("var bool name; name := 5");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("var bool name; name := 5");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("undefinedName");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("undefinedName");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("var undefinedType name; 1");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("var undefinedType name; 1");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("var bool endsWithDeclaration;");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("var bool endsWithDeclaration;");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("var bool var1; var var1 var2; var2 := 'c' ");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("var bool var1; var var1 var2; var2 := 'c' ");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,8 +82,8 @@ public class SimpleVariableTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctScopeChecking() {
|
||||
AllTests.checkFile("simpleScope.boppi");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.checkFile("simpleScope.boppi");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,14 +91,14 @@ public class SimpleVariableTest {
|
|||
*/
|
||||
@Test
|
||||
public void wrongScopeChecking() {
|
||||
AllTests.checkString("var bool var1; var bool var1; 1");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("var bool var1; var bool var1; 1");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("var bool var1; var char var1; 1");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("var bool var1; var char var1; 1");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
|
||||
AllTests.checkString("{ var int var1; var1 := 4}; var int var2; var1");
|
||||
assertThat(AllTests.log, hasSize(1));
|
||||
BoppiTests.checkString("{ var int var1; var1 := 4}; var int var2; var1");
|
||||
assertThat(BoppiTests.log, hasSize(1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,8 +106,8 @@ public class SimpleVariableTest {
|
|||
*/
|
||||
@Test
|
||||
public void correctVariableGeneration() {
|
||||
AllTests.compileAndRunFile("simpleVariable.boppi");
|
||||
assertThat(AllTests.log, is(empty()));
|
||||
BoppiTests.compileAndRunFile("simpleVariable.boppi");
|
||||
assertThat(BoppiTests.log, is(empty()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue