mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-14 09:30:57 +00:00
VariableBuilder has replaced VariableBuilderContext.
This commit is contained in:
parent
e103a783ce
commit
9811e48039
@ -15,6 +15,9 @@ import java.util.List;
|
||||
*/
|
||||
public class VariableBuilder {
|
||||
|
||||
/** The variable name. */
|
||||
private String varName;
|
||||
|
||||
/** The scope of the variable. */
|
||||
private Scope scope;
|
||||
|
||||
@ -30,12 +33,46 @@ public class VariableBuilder {
|
||||
/** The directives of the variable declaration. */
|
||||
private List<Directive> directives;
|
||||
|
||||
public VariableBuilder(Scope scope, boolean isParameter, SymbolType type, ArraySpec arraySpec, List<Directive> directives) {
|
||||
/** The data segment. */
|
||||
private String dataSegment;
|
||||
|
||||
public VariableBuilder(String varName, Scope scope, boolean isParameter, SymbolType type, ArraySpec arraySpec, List<Directive> directives, String dataSegment) {
|
||||
this.varName = varName;
|
||||
this.scope = scope;
|
||||
this.isParameter = isParameter;
|
||||
this.type = type;
|
||||
this.arraySpec = arraySpec;
|
||||
this.directives = directives;
|
||||
this.dataSegment = dataSegment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the variable with the properties derived from type, scope, directives and configuration.
|
||||
* @return The variable
|
||||
*/
|
||||
public Variable build() {
|
||||
Variable variable;
|
||||
if(isConstant()) {
|
||||
variable = Variable.createConstant(varName, type, scope, arraySpec, null, dataSegment);
|
||||
} else if(this.isSingleStaticAssignment()) {
|
||||
// Create single-static-assignment PHI-master variable
|
||||
variable = Variable.createPhiMaster(varName, type, scope, getMemoryArea(), dataSegment);
|
||||
} else {
|
||||
// Create multiple-assignment variable
|
||||
variable = Variable.createLoadStore(varName, type, scope, getMemoryArea(), dataSegment);
|
||||
}
|
||||
variable.setDeclaredConst(this.isConstant());
|
||||
variable.setDeclaredVolatile(this.isVolatile());
|
||||
variable.setDeclaredExport(this.isExport());
|
||||
variable.setDeclaredAsRegister(this.isOptimize());
|
||||
variable.setDeclaredRegister(this.getRegister());
|
||||
if(variable.getDeclaredRegister() instanceof Registers.RegisterMainMem) {
|
||||
((Registers.RegisterMainMem) variable.getDeclaredRegister()).setVariableRef(variable.getVariableRef());
|
||||
}
|
||||
variable.setMemoryArea(this.getMemoryArea());
|
||||
variable.setDeclaredAlignment(this.getAlignment());
|
||||
scope.add(variable);
|
||||
return variable;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,7 +211,8 @@ public class VariableBuilder {
|
||||
return hasDirective(Directive.ToConst.class);
|
||||
}
|
||||
|
||||
/** Declared as export (__export keyword)
|
||||
/**
|
||||
* Declared as export (__export keyword)
|
||||
*
|
||||
* @return true if declared as export
|
||||
*/
|
||||
@ -243,13 +281,14 @@ public class VariableBuilder {
|
||||
|
||||
/**
|
||||
* Get any memory-alignment of the variables data
|
||||
* @return
|
||||
*
|
||||
* @return The memory alignment
|
||||
*/
|
||||
public Integer getAlignment() {
|
||||
Directive.Align alignDirective = findDirective(Directive.Align.class);
|
||||
if(alignDirective != null) {
|
||||
if(isArray()) {
|
||||
return alignDirective.alignment;
|
||||
return alignDirective.alignment;
|
||||
} else {
|
||||
// TODO: Add information about which variable (name) and the offending source line
|
||||
throw new CompileError("Error! Cannot align variable that is not an array.");
|
||||
@ -294,11 +333,10 @@ public class VariableBuilder {
|
||||
* Examines whether a specific directive is present in the source
|
||||
*
|
||||
* @param directiveClass The class of the type to look for
|
||||
* @param directives The list of directives to search
|
||||
* @param <DirectiveClass> The class of the type to look for
|
||||
* @return true if the directive if found. false otherwise.
|
||||
*/
|
||||
private <DirectiveClass extends Directive> boolean hasDirective(Class<DirectiveClass> directiveClass) {
|
||||
public <DirectiveClass extends Directive> boolean hasDirective(Class<DirectiveClass> directiveClass) {
|
||||
return findDirective(directiveClass) != null;
|
||||
}
|
||||
|
||||
@ -306,7 +344,6 @@ public class VariableBuilder {
|
||||
* Look for a specific directive type in a list of directives
|
||||
*
|
||||
* @param directiveClass The class of the type to look for
|
||||
* @param directives The list of directives to search
|
||||
* @param <DirectiveClass> The class of the type to look for
|
||||
* @return The directive if found. null if not found.
|
||||
*/
|
||||
|
@ -1,110 +0,0 @@
|
||||
package dk.camelot64.kickc.model;
|
||||
|
||||
import dk.camelot64.kickc.model.statements.StatementSource;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used for creating {@link Variable}s with the right properties based on all their directives
|
||||
*/
|
||||
public class VariableBuilderContext {
|
||||
|
||||
public VariableBuilderContext() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies directives to a variable.
|
||||
*
|
||||
* @param lValue The variable to apply directives to
|
||||
* @param sourceDirectives The directives found in the source code
|
||||
* @param source The source line (for exceptions)
|
||||
*/
|
||||
public void applyDirectives(Variable lValue, boolean isParameter, boolean isArray, List<Directive> sourceDirectives, StatementSource source) {
|
||||
if(hasDirective(Directive.Const.class, sourceDirectives))
|
||||
lValue.setDeclaredConst(true);
|
||||
if(isArray)
|
||||
lValue.setDeclaredConst(true);
|
||||
if(hasDirective(Directive.Volatile.class, sourceDirectives))
|
||||
lValue.setDeclaredVolatile(true);
|
||||
if(hasDirective(Directive.Export.class, sourceDirectives))
|
||||
lValue.setDeclaredExport(true);
|
||||
if(hasDirective(Directive.Register.class, sourceDirectives)) {
|
||||
lValue.setMemoryArea(Variable.MemoryArea.ZEROPAGE_MEMORY);
|
||||
lValue.setDeclaredAsRegister(true);
|
||||
}
|
||||
if(isArray)
|
||||
lValue.setMemoryArea(Variable.MemoryArea.MAIN_MEMORY);
|
||||
if(hasDirective(Directive.MemZp.class, sourceDirectives))
|
||||
lValue.setMemoryArea(Variable.MemoryArea.ZEROPAGE_MEMORY);
|
||||
if(hasDirective(Directive.MemMain.class, sourceDirectives))
|
||||
lValue.setMemoryArea(Variable.MemoryArea.MAIN_MEMORY);
|
||||
Directive.Address addressDirective = findDirective(Directive.Address.class, sourceDirectives);
|
||||
if(addressDirective != null) {
|
||||
Variable.MemoryArea memoryArea = (addressDirective.address < 0x100) ? Variable.MemoryArea.ZEROPAGE_MEMORY : Variable.MemoryArea.MAIN_MEMORY;
|
||||
if(Variable.MemoryArea.ZEROPAGE_MEMORY.equals(memoryArea)) {
|
||||
lValue.setMemoryArea(Variable.MemoryArea.ZEROPAGE_MEMORY);
|
||||
Registers.Register register = new Registers.RegisterZpMem(addressDirective.address.intValue(), -1, true);
|
||||
lValue.setDeclaredRegister(register);
|
||||
} else {
|
||||
lValue.setMemoryArea(Variable.MemoryArea.MAIN_MEMORY);
|
||||
Registers.Register register = new Registers.RegisterMainMem((VariableRef) lValue.getRef(), -1, addressDirective.address);
|
||||
lValue.setDeclaredRegister(register);
|
||||
}
|
||||
}
|
||||
|
||||
Directive.NamedRegister registerDirective = findDirective(Directive.NamedRegister.class, sourceDirectives);
|
||||
if(registerDirective != null) {
|
||||
lValue.setDeclaredAsRegister(true);
|
||||
Registers.Register register = Registers.getRegister(registerDirective.name);
|
||||
if(register == null) {
|
||||
throw new CompileError("Error! Unknown register " + registerDirective.name, source);
|
||||
}
|
||||
lValue.setDeclaredRegister(register);
|
||||
}
|
||||
|
||||
Directive.Align alignDirective = findDirective(Directive.Align.class, sourceDirectives);
|
||||
if(alignDirective != null) {
|
||||
if(isArray) {
|
||||
lValue.setDeclaredAlignment(alignDirective.alignment);
|
||||
} else {
|
||||
throw new CompileError("Error! Cannot align variable that is not a string or an array " + lValue.toString(), source);
|
||||
}
|
||||
}
|
||||
// TODO: Add strategy for selecting main memory for non-pointer local variables
|
||||
}
|
||||
|
||||
/**
|
||||
* Examines whether a specific directive is present in the source
|
||||
*
|
||||
* @param directiveClass The class of the type to look for
|
||||
* @param directives The list of directives to search
|
||||
* @param <DirectiveClass> The class of the type to look for
|
||||
* @return true if the directive if found. false otherwise.
|
||||
*/
|
||||
private <DirectiveClass extends Directive> boolean hasDirective(Class<DirectiveClass> directiveClass, List<Directive> directives) {
|
||||
return findDirective(directiveClass, directives) != null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Look for a specific directive type in a list of directives
|
||||
*
|
||||
* @param directiveClass The class of the type to look for
|
||||
* @param directives The list of directives to search
|
||||
* @param <DirectiveClass> The class of the type to look for
|
||||
* @return The directive if found. null if not found.
|
||||
*/
|
||||
private <DirectiveClass extends Directive> DirectiveClass findDirective(Class<DirectiveClass> directiveClass, List<Directive> directives) {
|
||||
if(directives == null) return null;
|
||||
for(Directive directive : directives) {
|
||||
if(directiveClass.isInstance(directive)) {
|
||||
return (DirectiveClass) directive;
|
||||
}
|
||||
}
|
||||
// Not found!
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -103,7 +103,6 @@ public class Procedure extends Scope {
|
||||
public void setParameters(List<Variable> parameters) {
|
||||
this.parameterNames = new ArrayList<>();
|
||||
for(Variable parameter : parameters) {
|
||||
add(parameter);
|
||||
parameterNames.add(parameter.getLocalName());
|
||||
}
|
||||
}
|
||||
|
@ -125,9 +125,9 @@ public class Variable implements Symbol {
|
||||
this.type = type;
|
||||
this.scope = scope;
|
||||
this.arraySpec = arraySpec;
|
||||
this.initValue = initValue;
|
||||
this.dataSegment = dataSegment;
|
||||
this.memoryArea = memoryArea;
|
||||
this.initValue = initValue;
|
||||
this.comments = new ArrayList<>();
|
||||
setFullName();
|
||||
}
|
||||
|
@ -47,8 +47,6 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
private Stack<Scope> scopeStack;
|
||||
/** The memory area used by default for variables. */
|
||||
private Variable.MemoryArea defaultMemoryArea;
|
||||
/** Context used for adding directives to variables. */
|
||||
private VariableBuilderContext directiveContext;
|
||||
|
||||
public Pass0GenerateStatementSequence(CParser cParser, KickCParser.FileContext fileCtx, Program program) {
|
||||
this.cParser = cParser;
|
||||
@ -57,7 +55,6 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
this.sequence = program.getStatementSequence();
|
||||
this.scopeStack = new Stack<>();
|
||||
this.defaultMemoryArea = Variable.MemoryArea.ZEROPAGE_MEMORY;
|
||||
this.directiveContext = new VariableBuilderContext();
|
||||
scopeStack.push(program.getScope());
|
||||
}
|
||||
|
||||
@ -266,11 +263,12 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
@Override
|
||||
public Object visitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) {
|
||||
this.visitDeclTypes(ctx.declTypes());
|
||||
SymbolType type = declVarType;
|
||||
List<Directive> directives = declVarDirectives;
|
||||
Variable param = Variable.createPhiMaster(ctx.NAME().getText(), type, getCurrentScope(), defaultMemoryArea, currentDataSegment);
|
||||
// Add directives
|
||||
directiveContext.applyDirectives(param, true, false, directives, new StatementSource(ctx));
|
||||
String varName = ctx.NAME().getText();
|
||||
VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), true, declVarType, null, declVarDirectives, currentDataSegment);
|
||||
// TODO: const parameter pointer should be no-modify!
|
||||
if(varBuilder.hasDirective(Directive.Const.class))
|
||||
throw new CompileError("Error! Const parameters not supported " + varName + " in " + getCurrentScope().getFullName() + "()");
|
||||
Variable param = varBuilder.build();
|
||||
exitDeclTypes();
|
||||
return param;
|
||||
}
|
||||
@ -578,56 +576,18 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
PrePostModifierHandler.addPreModifiers(this, initializer, statementSource);
|
||||
RValue initValue = (initializer == null) ? null : (RValue) visit(initializer);
|
||||
initValue = Initializers.getInitValue(initValue, declVarType, declIsArray, declArraySize, program, statementSource);
|
||||
VariableBuilder varBuilder = new VariableBuilder(getCurrentScope(), false, declVarType, arraySpec, declVarDirectives);
|
||||
if(varBuilder.isConstant()) {
|
||||
Scope scope = getCurrentScope();
|
||||
VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), false, declVarType, arraySpec, declVarDirectives, currentDataSegment);
|
||||
Variable variable = varBuilder.build();
|
||||
if(variable.isKindConstant()) {
|
||||
// Set constant value
|
||||
ConstantValue constInitValue = getConstInitValue(initValue, initializer, statementSource);
|
||||
Variable constVar = Variable.createConstant(varName, declVarType, scope, arraySpec, constInitValue, currentDataSegment);
|
||||
constVar.setDeclaredConst(varBuilder.isConstant());
|
||||
constVar.setDeclaredVolatile(varBuilder.isVolatile());
|
||||
constVar.setDeclaredExport(varBuilder.isExport());
|
||||
constVar.setDeclaredAsRegister(varBuilder.isOptimize());
|
||||
constVar.setDeclaredRegister(varBuilder.getRegister());
|
||||
constVar.setMemoryArea(varBuilder.getMemoryArea());
|
||||
constVar.setDeclaredAlignment(varBuilder.getAlignment());
|
||||
scope.add(constVar);
|
||||
variable.setInitValue(constInitValue);
|
||||
// Add comments to constant
|
||||
constVar.setComments(ensureUnusedComments(declVarComments));
|
||||
} else if(varBuilder.isSingleStaticAssignment()) {
|
||||
// Create SSA PHI-master variable
|
||||
Variable lValue = Variable.createPhiMaster(varName, declVarType, getCurrentScope(), defaultMemoryArea, currentDataSegment);
|
||||
lValue.setDeclaredConst(varBuilder.isConstant());
|
||||
lValue.setDeclaredVolatile(varBuilder.isVolatile());
|
||||
lValue.setDeclaredExport(varBuilder.isExport());
|
||||
lValue.setDeclaredAsRegister(varBuilder.isOptimize());
|
||||
lValue.setDeclaredRegister(varBuilder.getRegister());
|
||||
if(lValue.getDeclaredRegister() instanceof Registers.RegisterMainMem) {
|
||||
((Registers.RegisterMainMem) lValue.getDeclaredRegister()).setVariableRef(lValue.getVariableRef());
|
||||
}
|
||||
lValue.setMemoryArea(varBuilder.getMemoryArea());
|
||||
lValue.setDeclaredAlignment(varBuilder.getAlignment());
|
||||
getCurrentScope().add(lValue);
|
||||
if(!declVarStructMember) {
|
||||
Statement initStmt = new StatementAssignment(lValue.getVariableRef(), initValue, statementSource, ensureUnusedComments(declVarComments));
|
||||
sequence.addStatement(initStmt);
|
||||
}
|
||||
} else {
|
||||
Variable lValue = Variable.createLoadStore(varName, declVarType, getCurrentScope(), defaultMemoryArea, currentDataSegment);
|
||||
lValue.setDeclaredConst(varBuilder.isConstant());
|
||||
lValue.setDeclaredVolatile(varBuilder.isVolatile());
|
||||
lValue.setDeclaredExport(varBuilder.isExport());
|
||||
lValue.setDeclaredAsRegister(varBuilder.isOptimize());
|
||||
lValue.setDeclaredRegister(varBuilder.getRegister());
|
||||
if(lValue.getDeclaredRegister() instanceof Registers.RegisterMainMem) {
|
||||
((Registers.RegisterMainMem) lValue.getDeclaredRegister()).setVariableRef(lValue.getVariableRef());
|
||||
}
|
||||
lValue.setMemoryArea(varBuilder.getMemoryArea());
|
||||
lValue.setDeclaredAlignment(varBuilder.getAlignment());
|
||||
getCurrentScope().add(lValue);
|
||||
if(!declVarStructMember) {
|
||||
Statement initStmt = new StatementAssignment(lValue.getVariableRef(), initValue, statementSource, ensureUnusedComments(declVarComments));
|
||||
sequence.addStatement(initStmt);
|
||||
}
|
||||
variable.setComments(ensureUnusedComments(declVarComments));
|
||||
}
|
||||
if(!variable.isKindConstant() && !declVarStructMember) {
|
||||
Statement initStmt = new StatementAssignment(variable.getVariableRef(), initValue, statementSource, ensureUnusedComments(declVarComments));
|
||||
sequence.addStatement(initStmt);
|
||||
}
|
||||
if(initializer != null)
|
||||
PrePostModifierHandler.addPostModifiers(this, initializer, statementSource);
|
||||
@ -687,11 +647,12 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
}
|
||||
// Add a constant variable
|
||||
Scope scope = getCurrentScope();
|
||||
Variable constVar = Variable.createConstant(varName, declVarType, scope, arraySpec, constantArrayKickAsm, currentDataSegment);
|
||||
scope.add(constVar);
|
||||
VariableBuilder varBuilder = new VariableBuilder(varName, scope, declIsArray, declVarType, arraySpec, declVarDirectives, currentDataSegment);
|
||||
Variable variable = varBuilder.build();
|
||||
// Set constant value
|
||||
variable.setInitValue(getConstInitValue(constantArrayKickAsm, null, statementSource));
|
||||
// Add comments to constant
|
||||
constVar.setComments(ensureUnusedComments(declVarComments));
|
||||
directiveContext.applyDirectives(constVar, false, declIsArray, declVarDirectives, statementSource);
|
||||
variable.setComments(ensureUnusedComments(declVarComments));
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -1171,25 +1132,17 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
BlockScope blockScope = getCurrentScope().addBlockScope();
|
||||
scopeStack.push(blockScope);
|
||||
loopStack.push(new Loop(blockScope, false));
|
||||
|
||||
StatementSource statementSource = StatementSource.forRanged(ctx);
|
||||
|
||||
// Create / find declared loop variable
|
||||
if(ctx.declTypes() != null) {
|
||||
this.visitDeclTypes(ctx.declTypes());
|
||||
}
|
||||
SymbolType varType = declVarType;
|
||||
List<Directive> varDirectives = declVarDirectives;
|
||||
String varName = ctx.NAME().getText();
|
||||
Variable lValue;
|
||||
if(varType != null) {
|
||||
try {
|
||||
lValue = getCurrentScope().add(Variable.createPhiMaster(varName, varType, getCurrentScope(), defaultMemoryArea, currentDataSegment));
|
||||
} catch(CompileError e) {
|
||||
throw new CompileError(e.getMessage(), statementSource);
|
||||
}
|
||||
// Add directives
|
||||
directiveContext.applyDirectives(lValue, false, false, varDirectives, statementSource);
|
||||
VariableBuilder varBuilder = new VariableBuilder(varName, blockScope, false, varType, null, declVarDirectives, currentDataSegment);
|
||||
lValue = varBuilder.build();
|
||||
} else {
|
||||
lValue = getCurrentScope().getVariable(varName);
|
||||
if(lValue == null) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user