package eu.wietsevenema.lang.oberon.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import xtc.tree.VisitingException;
import eu.wietsevenema.lang.oberon.ast.declarations.ConstantDecl;
import eu.wietsevenema.lang.oberon.ast.declarations.Declarations;
import eu.wietsevenema.lang.oberon.ast.declarations.ProcedureDecl;
import eu.wietsevenema.lang.oberon.ast.declarations.TypeDecl;
import eu.wietsevenema.lang.oberon.ast.declarations.VarDecl;
import eu.wietsevenema.lang.oberon.ast.expressions.Identifier;
import eu.wietsevenema.lang.oberon.ast.expressions.IntegerConstant;
import eu.wietsevenema.lang.oberon.ast.statements.AssignmentStatement;
import eu.wietsevenema.lang.oberon.ast.types.IntegerType;
import eu.wietsevenema.lang.oberon.ast.types.TypeAlias;
import eu.wietsevenema.lang.oberon.ast.visitors.interpreter.DeclarationEvaluator;
import eu.wietsevenema.lang.oberon.ast.visitors.interpreter.StatementEvaluator;
import eu.wietsevenema.lang.oberon.exceptions.ImmutableException;
import eu.wietsevenema.lang.oberon.exceptions.ValueUndefinedException;
import eu.wietsevenema.lang.oberon.exceptions.SymbolNotDeclaredException;
import eu.wietsevenema.lang.oberon.interpreter.InterpreterScope;
import eu.wietsevenema.lang.oberon.interpreter.values.IntegerValue;
public class DeclarationEvaluatorTest {
InterpreterScope scope;
@Before
public void setUp() throws Exception {
scope = new InterpreterScope();
}
@Test
public void testVarDeclaration() throws SymbolNotDeclaredException {
List<Identifier> identifiers = new ArrayList<Identifier>();
identifiers.add(new Identifier("a"));
identifiers.add(new Identifier("b"));
identifiers.add(new Identifier("c"));
VarDecl varDecl = new VarDecl(identifiers, new IntegerType());
DeclarationEvaluator eval = new DeclarationEvaluator(scope);
eval.dispatch(varDecl);
assertNotNull(scope.lookupValue("a"));
assertNotNull(scope.lookupValue("b"));
assertNotNull(scope.lookupValue("c"));
}
public void testConstDeclaration() throws SymbolNotDeclaredException, ValueUndefinedException {
Identifier identifier = new Identifier("a");
ConstantDecl constDecl = new ConstantDecl(identifier, new IntegerConstant(1));
DeclarationEvaluator eval = new DeclarationEvaluator(scope);
eval.dispatch(constDecl);
assertEquals(((IntegerValue) scope.lookupValue("a")).getValue(), new Integer(1));
}
@Test
public void testTypeDeclaration() throws SymbolNotDeclaredException, ValueUndefinedException {
/*
* Declare myType as an alias of Integer.
*/
List<ConstantDecl> cds = new ArrayList<ConstantDecl>();
List<TypeDecl> tds = new ArrayList<TypeDecl>();
List<VarDecl> vds = new ArrayList<VarDecl>();
List<ProcedureDecl> pds = new ArrayList<ProcedureDecl>();
TypeDecl typeDecl = new TypeDecl(new Identifier("myType"), new IntegerType());
tds.add(typeDecl);
List<Identifier> ids = new ArrayList<Identifier>();
ids.add(new Identifier("a"));
VarDecl varDecl = new VarDecl(ids, new TypeAlias(new Identifier("myType")));
vds.add(varDecl);
Declarations decls = new Declarations(cds, tds, vds, pds);
DeclarationEvaluator eval = new DeclarationEvaluator(scope);
eval.dispatch(decls);
/*
* Assign 'a' with an integer value. All should be well.
*/
AssignmentStatement assign = new AssignmentStatement(new Identifier("a"), new IntegerConstant(999));
StatementEvaluator se = new StatementEvaluator(scope);
se.dispatch(assign);
/*
* After the assign, the value should be assigned.
*/
assertEquals(((IntegerValue) scope.lookupValue("a")).getValue(), new Integer(999));
}
@Test(expected = ImmutableException.class)
public void testAssignConstFails() throws Throwable {
Identifier identifier = new Identifier("a");
ConstantDecl constDecl = new ConstantDecl(identifier, new IntegerConstant(1));
DeclarationEvaluator eval = new DeclarationEvaluator(scope);
eval.dispatch(constDecl);
AssignmentStatement assign = new AssignmentStatement(identifier, new IntegerConstant(2));
try {
StatementEvaluator statEval = new StatementEvaluator(scope);
statEval.dispatch(assign);
} catch (VisitingException e) {
throw e.getCause();
}
}
}