Skip to content

Commit

Permalink
Added re-assignment checking for constants
Browse files Browse the repository at this point in the history
  • Loading branch information
SamTebbs33 committed Dec 2, 2015
1 parent b04840a commit bccce6c
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 17 deletions.
3 changes: 2 additions & 1 deletion Test.ash
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import Ifc2
public class Test {

public static func main(args : [String]) {

const c = 299792458
c = 0
}

}
1 change: 1 addition & 0 deletions src/ashc/error/AshError.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public enum EnumError {

PRIMTIVE_CANNOT_BE_OPTIONAL("A primitive type cannot be optional (%s)"),
CANNOT_ASSIGN("Cannot assign %s to %s"),
ASSIGNMENT_OF_CONST("A const (\'%s\') cannot be reassigned"),
CLOSURE_TYPE_NOT_INTERFACE("The type used is not an interface"),
NO_INTERFACE_FOR_CLOSURE_FOUND("None of the imported interfaces have a function that is applicable to the given arguments and return type");

Expand Down
26 changes: 16 additions & 10 deletions src/ashc/grammar/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -380,10 +380,10 @@ public void preAnalyse() {
arg.preAnalyse();
if (!arg.errored) {
final TypeI argType = arg.type.toTypeI();
final Variable local = new Variable(arg.id, argType);
final Variable local = new Variable(arg.id, argType, false);
local.isLocal = true;
defConstructorScope.addVar(local);
final Field field = new Field(Scope.getNamespace().copy().add(arg.id), EnumModifier.PUBLIC.intVal, argType, false, false, type);
final Field field = new Field(Scope.getNamespace().copy().add(arg.id), EnumModifier.PUBLIC.intVal, argType, false, false, false, type);
type.addField(field);
argFields.add(field);
defConstructor.parameters.add(argType);
Expand Down Expand Up @@ -1069,7 +1069,7 @@ private void finishPreAnalysis() {
scope = new FuncScope(returnType, isMutFunc, isGlobal || func.isStatic(), isGlobal, extType);
Scope.push(scope);
for (final NodeArg arg : args.args)
Semantics.addVar(new Variable(arg.id, arg.type.toTypeI()));
Semantics.addVar(new Variable(arg.id, arg.type.toTypeI(), false));

if (!isMutFunc && !isConstructor) {
if (!type.id.equals("void")) returnType = type.toTypeI();
Expand Down Expand Up @@ -1246,7 +1246,7 @@ protected void analyseProperty(final TypeI type) {
}
if (setBlock != null) {
Scope.push(new PropertyScope(var));
final Variable newVar = new Variable("newVal", var.type);
final Variable newVar = new Variable("newVal", var.type, false);
newVar.localID = var.isStatic() ? 0 : 1;
Scope.getScope().addVar(newVar);
setBlock.analyse(null);
Expand Down Expand Up @@ -1292,6 +1292,10 @@ public void generate() {
}
}

public boolean isConst() {
return keyword.equals("const");
}

}

public static class NodeVarDecExplicit extends NodeVarDec {
Expand All @@ -1311,7 +1315,7 @@ public void preAnalyse() {
if (mod.asInt() == EnumModifier.STATIC.intVal) isStatic = true;
modifiers |= mod.asInt();
}
var = new Field(name, modifiers, type.toTypeI(), setBlock != null, getBlock != null, Semantics.currentType());
var = new Field(name, modifiers, type.toTypeI(), setBlock != null, getBlock != null, isConst(), Semantics.currentType());
if (!Semantics.fieldExists(var)) Semantics.addField(var);
else semanticError(this, line, column, FIELD_ALREADY_EXISTS, id);
}
Expand All @@ -1331,7 +1335,7 @@ public void analyse(TypeI typeContext) {
semanticError(this, line, column, MISSING_ASSIGNMENT);
}
if (var == null) {
var = new Variable(id, typeI);
var = new Variable(id, typeI, isConst());
Semantics.addVar((Variable) var);
}
analyseProperty(typeI);
Expand All @@ -1356,7 +1360,7 @@ public void preAnalyse() {
}
expr.analyse(null);
typeI = expr.getExprType();
var = new Field(name, modifiers, typeI, setBlock != null, getBlock != null, Semantics.currentType());
var = new Field(name, modifiers, typeI, setBlock != null, getBlock != null, isConst(), Semantics.currentType());
if (!Semantics.fieldExists(var)) Semantics.addField(var);
else semanticError(this, line, column, FIELD_ALREADY_EXISTS, id);
}
Expand All @@ -1368,7 +1372,7 @@ public void analyse(TypeI typeContext) {
if (!((Node) expr).errored) {
final TypeI type = Semantics.filterNullType(expr.getExprType());
if (var == null) {
var = new Variable(id, type);
var = new Variable(id, type, isConst());
Semantics.addVar((Variable) var);
}
analyseProperty(type);
Expand Down Expand Up @@ -1775,6 +1779,8 @@ public void analyse(TypeI typeContext) {
expr.analyse(null);
final TypeI exprType = expr.getExprType();
var.analyse(null);
Field v = Semantics.getVar(var.id);
if (v != null && v.isConstant) semanticError(this, var.line, var.column, ASSIGNMENT_OF_CONST, v.id);
if (var.errored) errored = true;
if (var.var != null) if (!var.var.type.canBeAssignedTo(expr.getExprType()))
semanticError(this, line, column, CANNOT_ASSIGN, var.var.type, exprType);
Expand Down Expand Up @@ -2789,7 +2795,7 @@ public void analyse(TypeI typeContext) {
} else semanticError(this, line, column, CANNOT_ITERATE_TYPE, exprType);
}
Scope.push(new Scope(true));
var = new Variable(varId, varType);
var = new Variable(varId, varType, false);
Scope.getFuncScope().locals += exprType.isArray() ? 3 : 1; // Some local vars are reserved for use in the bytecode
Semantics.addVar(var);
block.analyse(null);
Expand Down Expand Up @@ -3642,7 +3648,7 @@ public void analyse(TypeI typeContext) {
argTypes = args.toTypeIList();
Scope.push(new FuncScope(typeI, false, false, false));
int i = 0;
for (TypeI arg : argTypes) Scope.getScope().addVar(new Variable(args.args.get(i++).id, arg));
for (TypeI arg : argTypes) Scope.getScope().addVar(new Variable(args.args.get(i++).id, arg, false));
body.analyse(null);
Scope.pop();
}
Expand Down
11 changes: 6 additions & 5 deletions src/ashc/semantics/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,8 @@ public boolean hasEqualSignature(Function superFunc) {

public static class Variable extends Field {

public Variable(final String id, final TypeI type) {
super(new QualifiedName(id), 0, type, false, false, Semantics.currentType());
public Variable(final String id, final TypeI type, boolean isConstant) {
super(new QualifiedName(id), 0, type, false, false, isConstant, Semantics.currentType());
if (Scope.inFuncScope()) {
isLocal = true;
localID = ++Scope.getFuncScope().locals;
Expand All @@ -339,19 +339,20 @@ public static class Field extends Member {
public TypeI type;
public String id;
public int localID;
public boolean isSetProperty, isGetProperty;
public boolean isSetProperty, isGetProperty, isConstant;

public Field(final QualifiedName qualifiedName, final int modifiers, final TypeI type, final boolean isSetProperty, final boolean isGetProperty, final Type enclosingType) {
public Field(final QualifiedName qualifiedName, final int modifiers, final TypeI type, final boolean isSetProperty, final boolean isGetProperty, final boolean isConstant, final Type enclosingType) {
super(qualifiedName, modifiers);
id = qualifiedName.shortName;
this.type = type;
this.enclosingType = enclosingType;
this.isGetProperty = isGetProperty;
this.isSetProperty = isSetProperty;
this.isConstant = isConstant;
}

public Field(final FieldNode fNode, final Type enclosing) {
this(new QualifiedName(fNode.name.replace('/', '.')), fNode.access, TypeI.fromBytecodeName(fNode.desc.replace(";", "")), false, false, enclosing);
this(new QualifiedName(fNode.name.replace('/', '.')), fNode.access, TypeI.fromBytecodeName(fNode.desc.replace(";", "")), false, false, BitOp.or(fNode.access, EnumModifier.FINAL.intVal), enclosing);
}

@Override
Expand Down
3 changes: 2 additions & 1 deletion src/ashc/semantics/Semantics.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ public static void addField(final Field field) {
public static Field getVar(final String id, final TypeI type) {
if (type.isTuple()) {
for (final TypeI tupleType : type.tupleTypes)
if ((tupleType.tupleName != null) && tupleType.tupleName.equals(id)) return new Variable(id, tupleType);
if ((tupleType.tupleName != null) && tupleType.tupleName.equals(id))
return new Variable(id, tupleType, false);
} else {
final Optional<Type> t = getType(type.shortName);
if (t.isPresent()) return t.get().getField(id);
Expand Down

0 comments on commit bccce6c

Please sign in to comment.