mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-11 04:37:29 +00:00
Working on type parser rewrite
This commit is contained in:
parent
09d11f220b
commit
823f2d7804
@ -150,17 +150,23 @@ public class StatementSource implements Serializable {
|
||||
}
|
||||
|
||||
public static StatementSource procedureBegin(KickCParser.DeclFunctionContext ctx) {
|
||||
return new StatementSource(ctx);
|
||||
/*
|
||||
final KickCParser.DeclFunctionBodyContext bodyCtx = ctx.declFunctionBody();
|
||||
ParseTree nodeStart = bodyCtx;
|
||||
ParseTree nodeStop = bodyCtx.getChild(bodyCtx.getChildCount() - 4);
|
||||
return new StatementSource(nodeStart, nodeStop);
|
||||
*/
|
||||
}
|
||||
|
||||
public static StatementSource procedureEnd(KickCParser.DeclFunctionContext ctx) {
|
||||
return new StatementSource(ctx);
|
||||
/*
|
||||
final KickCParser.DeclFunctionBodyContext bodyCtx = ctx.declFunctionBody();
|
||||
ParseTree nodeStart = bodyCtx.getChild(bodyCtx.getChildCount() - 1);
|
||||
ParseTree nodeStop = bodyCtx;
|
||||
return new StatementSource(nodeStart, nodeStop);
|
||||
*/
|
||||
}
|
||||
|
||||
public static StatementSource asm(KickCParser.StmtAsmContext ctx) {
|
||||
|
@ -8,13 +8,16 @@ import dk.camelot64.kickc.model.values.ProcedureRef;
|
||||
import dk.camelot64.kickc.passes.Pass1ByteXIntrinsicRewrite;
|
||||
import dk.camelot64.kickc.passes.Pass1PrintfIntrinsicRewrite;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/** Symbol describing a procedure/function */
|
||||
public class Procedure extends Scope {
|
||||
|
||||
/** The return type. {@link SymbolType#VOID} if the procedure does not return a value. */
|
||||
private final SymbolType returnType;
|
||||
private final SymbolTypeProcedure procedureType;
|
||||
/** The names of the parameters of the procedure. */
|
||||
private List<String> parameterNames;
|
||||
/** True if the parameter list ends with a variable length parameter list "..." */
|
||||
@ -78,9 +81,9 @@ public class Procedure extends Scope {
|
||||
/** The calling convention used for this procedure. */
|
||||
private CallingConvention callingConvention;
|
||||
|
||||
public Procedure(String name, SymbolType returnType, Scope parentScope, String codeSegment, String dataSegment, CallingConvention callingConvention) {
|
||||
public Procedure(String name, SymbolTypeProcedure procedureType, Scope parentScope, String codeSegment, String dataSegment, CallingConvention callingConvention) {
|
||||
super(name, parentScope, dataSegment);
|
||||
this.returnType = returnType;
|
||||
this.procedureType = procedureType;
|
||||
this.declaredInline = false;
|
||||
this.interruptType = null;
|
||||
this.comments = new ArrayList<>();
|
||||
@ -127,7 +130,7 @@ public class Procedure extends Scope {
|
||||
}
|
||||
|
||||
public SymbolType getReturnType() {
|
||||
return returnType;
|
||||
return procedureType.getReturnType();
|
||||
}
|
||||
|
||||
public List<Variable> getParameters() {
|
||||
@ -172,7 +175,7 @@ public class Procedure extends Scope {
|
||||
|
||||
@Override
|
||||
public SymbolType getType() {
|
||||
return new SymbolTypeProcedure(returnType);
|
||||
return procedureType;
|
||||
}
|
||||
|
||||
public boolean isDeclaredInline() {
|
||||
@ -245,7 +248,7 @@ public class Procedure extends Scope {
|
||||
if(interruptType != null) {
|
||||
res.append("__interrupt(").append(interruptType).append(") ");
|
||||
}
|
||||
res.append(returnType.getTypeName()).append(" ").append(getFullName()).append("(");
|
||||
res.append(getReturnType().getTypeName()).append(" ").append(getFullName()).append("(");
|
||||
boolean first = true;
|
||||
if(parameterNames != null) {
|
||||
for(Variable parameter : getParameters()) {
|
||||
@ -271,18 +274,22 @@ public class Procedure extends Scope {
|
||||
if(o == null || getClass() != o.getClass()) return false;
|
||||
if(!super.equals(o)) return false;
|
||||
Procedure procedure = (Procedure) o;
|
||||
return declaredInline == procedure.declaredInline &&
|
||||
Objects.equals(returnType, procedure.returnType) &&
|
||||
return variableLengthParameterList == procedure.variableLengthParameterList &&
|
||||
declaredInline == procedure.declaredInline &&
|
||||
declaredIntrinsic == procedure.declaredIntrinsic &&
|
||||
isConstructor == procedure.isConstructor &&
|
||||
Objects.equals(procedureType, procedure.procedureType) &&
|
||||
Objects.equals(parameterNames, procedure.parameterNames) &&
|
||||
Objects.equals(interruptType, procedure.interruptType) &&
|
||||
Objects.equals(comments, procedure.comments) &&
|
||||
Objects.equals(reservedZps, procedure.reservedZps) &&
|
||||
Objects.equals(codeSegment, procedure.codeSegment) &&
|
||||
Objects.equals(constructorRefs, procedure.constructorRefs) &&
|
||||
callingConvention == procedure.callingConvention;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), returnType, parameterNames, declaredInline, interruptType, comments, reservedZps, codeSegment, callingConvention);
|
||||
return Objects.hash(super.hashCode(), procedureType, parameterNames, variableLengthParameterList, declaredInline, declaredIntrinsic, interruptType, comments, reservedZps, codeSegment, constructorRefs, isConstructor, callingConvention);
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ public interface SymbolType extends Serializable {
|
||||
SymbolTypeNamed LABEL = new SymbolTypeNamed("label", 1, false, false);
|
||||
/** Void type representing no value. */
|
||||
SymbolTypeNamed VOID = new SymbolTypeNamed("void", 0, false, false);
|
||||
/** Value List type representing a "..." parameter list. */
|
||||
SymbolTypeNamed PARAM_LIST = new SymbolTypeNamed("param_list", 0, false, false);
|
||||
/** An unresolved type. Will be infered later. */
|
||||
SymbolTypeNamed VAR = new SymbolTypeNamed("var", -1, false, false);
|
||||
|
||||
|
@ -1,14 +1,17 @@
|
||||
package dk.camelot64.kickc.model.types;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/** A function returning another type */
|
||||
public class SymbolTypeProcedure implements SymbolType {
|
||||
|
||||
private SymbolType returnType;
|
||||
private List<SymbolType> paramTypes;
|
||||
|
||||
public SymbolTypeProcedure(SymbolType returnType) {
|
||||
public SymbolTypeProcedure(SymbolType returnType, List<SymbolType> paramTypes) {
|
||||
this.returnType = returnType;
|
||||
this.paramTypes = paramTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -35,9 +38,28 @@ public class SymbolTypeProcedure implements SymbolType {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
public List<SymbolType> getParamTypes() {
|
||||
return paramTypes;
|
||||
}
|
||||
|
||||
public void setParamTypes(List<SymbolType> paramTypes) {
|
||||
this.paramTypes = paramTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeBaseName() {
|
||||
return returnType.getTypeName() + "()";
|
||||
final StringBuilder typeBaseName = new StringBuilder();
|
||||
typeBaseName.append(returnType.getTypeBaseName());
|
||||
typeBaseName.append("(");
|
||||
boolean first = true;
|
||||
for(SymbolType paramType : paramTypes) {
|
||||
if(!first)
|
||||
typeBaseName.append(",");
|
||||
first = false;
|
||||
typeBaseName.append(paramType.getTypeBaseName());
|
||||
}
|
||||
typeBaseName.append(")");
|
||||
return typeBaseName.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,11 +72,13 @@ public class SymbolTypeProcedure implements SymbolType {
|
||||
if(this == o) return true;
|
||||
if(o == null || getClass() != o.getClass()) return false;
|
||||
SymbolTypeProcedure that = (SymbolTypeProcedure) o;
|
||||
return Objects.equals(returnType, that.returnType);
|
||||
return Objects.equals(returnType, that.returnType) &&
|
||||
Objects.equals(paramTypes, that.paramTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(returnType);
|
||||
return Objects.hash(returnType, paramTypes);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ typeSpecifier
|
||||
|
||||
declarator
|
||||
: NAME {if(isTypedef) { cParser.addTypedef($NAME.text); isTypedef=false; } } #declaratorName
|
||||
| declarator PAR_BEGIN parameterListDecl? PAR_END #declaratorProcedure
|
||||
| declarator BRACKET_BEGIN (expr)? BRACKET_END #declaratorArray
|
||||
| ASTERISK directive* declarator #declaratorPointer
|
||||
| PAR_BEGIN declarator PAR_END #declaratorPar
|
||||
@ -80,7 +81,6 @@ declarator
|
||||
type
|
||||
: SIMPLETYPE #typeSimple
|
||||
| SIGNEDNESS SIMPLETYPE? #typeSignedSimple
|
||||
| type PAR_BEGIN PAR_END #typeProcedure // TODO: Move to declarator
|
||||
| structDef #typeStructDef
|
||||
| structRef #typeStructRef
|
||||
| enumDef #typeEnumDef
|
||||
@ -118,11 +118,7 @@ enumMember
|
||||
;
|
||||
|
||||
declFunction
|
||||
: declType declarator PAR_BEGIN parameterListDecl? PAR_END (declFunctionBody | ';' )
|
||||
;
|
||||
|
||||
declFunctionBody
|
||||
: CURLY_BEGIN stmtSeq? CURLY_END
|
||||
: declType declarator CURLY_BEGIN stmtSeq? CURLY_END
|
||||
;
|
||||
|
||||
parameterListDecl
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -222,25 +222,13 @@ public class KickCParserBaseListener implements KickCParserListener {
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterTypeProcedure(KickCParser.TypeProcedureContext ctx) { }
|
||||
@Override public void enterDeclaratorProcedure(KickCParser.DeclaratorProcedureContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitTypeProcedure(KickCParser.TypeProcedureContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterTypeStructRef(KickCParser.TypeStructRefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitTypeStructRef(KickCParser.TypeStructRefContext ctx) { }
|
||||
@Override public void exitDeclaratorProcedure(KickCParser.DeclaratorProcedureContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -253,6 +241,18 @@ public class KickCParserBaseListener implements KickCParserListener {
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitTypeSimple(KickCParser.TypeSimpleContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -270,25 +270,25 @@ public class KickCParserBaseListener implements KickCParserListener {
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterTypeNamedRef(KickCParser.TypeNamedRefContext ctx) { }
|
||||
@Override public void enterTypeStructRef(KickCParser.TypeStructRefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitTypeNamedRef(KickCParser.TypeNamedRefContext ctx) { }
|
||||
@Override public void exitTypeStructRef(KickCParser.TypeStructRefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { }
|
||||
@Override public void enterTypeEnumDef(KickCParser.TypeEnumDefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { }
|
||||
@Override public void exitTypeEnumDef(KickCParser.TypeEnumDefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -306,13 +306,13 @@ public class KickCParserBaseListener implements KickCParserListener {
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterTypeEnumDef(KickCParser.TypeEnumDefContext ctx) { }
|
||||
@Override public void enterTypeNamedRef(KickCParser.TypeNamedRefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitTypeEnumDef(KickCParser.TypeEnumDefContext ctx) { }
|
||||
@Override public void exitTypeNamedRef(KickCParser.TypeNamedRefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -409,18 +409,6 @@ public class KickCParserBaseListener implements KickCParserListener {
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitDeclFunction(KickCParser.DeclFunctionContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterDeclFunctionBody(KickCParser.DeclFunctionBodyContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitDeclFunctionBody(KickCParser.DeclFunctionBodyContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -138,14 +138,7 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitTypeProcedure(KickCParser.TypeProcedureContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitTypeStructRef(KickCParser.TypeStructRefContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitDeclaratorProcedure(KickCParser.DeclaratorProcedureContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -153,6 +146,13 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitTypeSimple(KickCParser.TypeSimpleContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -166,14 +166,14 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitTypeNamedRef(KickCParser.TypeNamedRefContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitTypeStructRef(KickCParser.TypeStructRefContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitTypeEnumDef(KickCParser.TypeEnumDefContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -187,7 +187,7 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitTypeEnumDef(KickCParser.TypeEnumDefContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitTypeNamedRef(KickCParser.TypeNamedRefContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -244,13 +244,6 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitDeclFunction(KickCParser.DeclFunctionContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitDeclFunctionBody(KickCParser.DeclFunctionBodyContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -198,29 +198,17 @@ public interface KickCParserListener extends ParseTreeListener {
|
||||
*/
|
||||
void exitDeclaratorName(KickCParser.DeclaratorNameContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code typeProcedure}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* Enter a parse tree produced by the {@code declaratorProcedure}
|
||||
* labeled alternative in {@link KickCParser#declarator}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterTypeProcedure(KickCParser.TypeProcedureContext ctx);
|
||||
void enterDeclaratorProcedure(KickCParser.DeclaratorProcedureContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code typeProcedure}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* Exit a parse tree produced by the {@code declaratorProcedure}
|
||||
* labeled alternative in {@link KickCParser#declarator}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitTypeProcedure(KickCParser.TypeProcedureContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code typeStructRef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterTypeStructRef(KickCParser.TypeStructRefContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code typeStructRef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitTypeStructRef(KickCParser.TypeStructRefContext ctx);
|
||||
void exitDeclaratorProcedure(KickCParser.DeclaratorProcedureContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code typeSimple}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
@ -233,6 +221,18 @@ public interface KickCParserListener extends ParseTreeListener {
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitTypeSimple(KickCParser.TypeSimpleContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code typeSignedSimple}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code typeSignedSimple}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code typeStructDef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
@ -246,29 +246,29 @@ public interface KickCParserListener extends ParseTreeListener {
|
||||
*/
|
||||
void exitTypeStructDef(KickCParser.TypeStructDefContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code typeNamedRef}
|
||||
* Enter a parse tree produced by the {@code typeStructRef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterTypeNamedRef(KickCParser.TypeNamedRefContext ctx);
|
||||
void enterTypeStructRef(KickCParser.TypeStructRefContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code typeNamedRef}
|
||||
* Exit a parse tree produced by the {@code typeStructRef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitTypeNamedRef(KickCParser.TypeNamedRefContext ctx);
|
||||
void exitTypeStructRef(KickCParser.TypeStructRefContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code typeSignedSimple}
|
||||
* Enter a parse tree produced by the {@code typeEnumDef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx);
|
||||
void enterTypeEnumDef(KickCParser.TypeEnumDefContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code typeSignedSimple}
|
||||
* Exit a parse tree produced by the {@code typeEnumDef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx);
|
||||
void exitTypeEnumDef(KickCParser.TypeEnumDefContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code typeEnumRef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
@ -282,17 +282,17 @@ public interface KickCParserListener extends ParseTreeListener {
|
||||
*/
|
||||
void exitTypeEnumRef(KickCParser.TypeEnumRefContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code typeEnumDef}
|
||||
* Enter a parse tree produced by the {@code typeNamedRef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterTypeEnumDef(KickCParser.TypeEnumDefContext ctx);
|
||||
void enterTypeNamedRef(KickCParser.TypeNamedRefContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code typeEnumDef}
|
||||
* Exit a parse tree produced by the {@code typeNamedRef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitTypeEnumDef(KickCParser.TypeEnumDefContext ctx);
|
||||
void exitTypeNamedRef(KickCParser.TypeNamedRefContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link KickCParser#structRef}.
|
||||
* @param ctx the parse tree
|
||||
@ -373,16 +373,6 @@ public interface KickCParserListener extends ParseTreeListener {
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitDeclFunction(KickCParser.DeclFunctionContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link KickCParser#declFunctionBody}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterDeclFunctionBody(KickCParser.DeclFunctionBodyContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link KickCParser#declFunctionBody}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitDeclFunctionBody(KickCParser.DeclFunctionBodyContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link KickCParser#parameterListDecl}.
|
||||
* @param ctx the parse tree
|
||||
|
@ -124,19 +124,12 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
|
||||
*/
|
||||
T visitDeclaratorName(KickCParser.DeclaratorNameContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code typeProcedure}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* Visit a parse tree produced by the {@code declaratorProcedure}
|
||||
* labeled alternative in {@link KickCParser#declarator}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitTypeProcedure(KickCParser.TypeProcedureContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code typeStructRef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitTypeStructRef(KickCParser.TypeStructRefContext ctx);
|
||||
T visitDeclaratorProcedure(KickCParser.DeclaratorProcedureContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code typeSimple}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
@ -144,6 +137,13 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitTypeSimple(KickCParser.TypeSimpleContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code typeSignedSimple}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code typeStructDef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
@ -152,19 +152,19 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
|
||||
*/
|
||||
T visitTypeStructDef(KickCParser.TypeStructDefContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code typeNamedRef}
|
||||
* Visit a parse tree produced by the {@code typeStructRef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitTypeNamedRef(KickCParser.TypeNamedRefContext ctx);
|
||||
T visitTypeStructRef(KickCParser.TypeStructRefContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code typeSignedSimple}
|
||||
* Visit a parse tree produced by the {@code typeEnumDef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx);
|
||||
T visitTypeEnumDef(KickCParser.TypeEnumDefContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code typeEnumRef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
@ -173,12 +173,12 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
|
||||
*/
|
||||
T visitTypeEnumRef(KickCParser.TypeEnumRefContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code typeEnumDef}
|
||||
* Visit a parse tree produced by the {@code typeNamedRef}
|
||||
* labeled alternative in {@link KickCParser#type}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitTypeEnumDef(KickCParser.TypeEnumDefContext ctx);
|
||||
T visitTypeNamedRef(KickCParser.TypeNamedRefContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link KickCParser#structRef}.
|
||||
* @param ctx the parse tree
|
||||
@ -227,12 +227,6 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitDeclFunction(KickCParser.DeclFunctionContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link KickCParser#declFunctionBody}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitDeclFunctionBody(KickCParser.DeclFunctionBodyContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link KickCParser#parameterListDecl}.
|
||||
* @param ctx the parse tree
|
||||
|
@ -116,7 +116,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
Procedure initProc = program.getScope().getLocalProcedure(SymbolRef.INIT_PROC_NAME);
|
||||
if(initProc == null) {
|
||||
// Create the _init() procedure
|
||||
initProc = new Procedure(SymbolRef.INIT_PROC_NAME, SymbolType.VOID, program.getScope(), Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT, Procedure.CallingConvention.PHI_CALL);
|
||||
initProc = new Procedure(SymbolRef.INIT_PROC_NAME, new SymbolTypeProcedure(SymbolType.VOID, new ArrayList<>()), program.getScope(), Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT, Procedure.CallingConvention.PHI_CALL);
|
||||
initProc.setDeclaredInline(true);
|
||||
initProc.setParameters(new ArrayList<>());
|
||||
program.getScope().add(initProc);
|
||||
@ -173,7 +173,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
// Add the _start() procedure to the program
|
||||
{
|
||||
program.setStartProcedure(new ProcedureRef(SymbolRef.START_PROC_NAME));
|
||||
final Procedure startProcedure = new Procedure(SymbolRef.START_PROC_NAME, SymbolType.VOID, program.getScope(), Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT, Procedure.CallingConvention.PHI_CALL);
|
||||
final Procedure startProcedure = new Procedure(SymbolRef.START_PROC_NAME, new SymbolTypeProcedure(SymbolType.VOID, new ArrayList<>()), program.getScope(), Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT, Procedure.CallingConvention.PHI_CALL);
|
||||
startProcedure.setParameters(new ArrayList<>());
|
||||
program.getScope().add(startProcedure);
|
||||
final ProcedureCompilation startProcedureCompilation = program.createProcedureCompilation(startProcedure.getRef());
|
||||
@ -391,83 +391,70 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
public Object visitDeclFunction(KickCParser.DeclFunctionContext ctx) {
|
||||
this.visit(ctx.declType());
|
||||
this.visit(ctx.declarator());
|
||||
SymbolType type = varDecl.getEffectiveType();
|
||||
List<Directive> directives = varDecl.getDeclDirectives();
|
||||
String name = varDecl.getVarName();
|
||||
Procedure procedure = new Procedure(name, type, program.getScope(), currentCodeSegment, currentDataSegment, currentCallingConvention);
|
||||
addDirectives(procedure, directives, StatementSource.procedureDecl(ctx));
|
||||
StatementSource declSource = new StatementSource((ParserRuleContext) ctx.parent.parent);
|
||||
Procedure procedure = new Procedure(varDecl.getVarName(), (SymbolTypeProcedure) varDecl.declType, program.getScope(), currentCodeSegment, currentDataSegment, currentCallingConvention);
|
||||
addDirectives(procedure, varDecl.getDeclDirectives(), declSource);
|
||||
procedure.setComments(ensureUnusedComments(getCommentsSymbol(ctx)));
|
||||
// TODO: Detect existing declarations and check for match!
|
||||
program.getScope().add(procedure);
|
||||
program.createProcedureCompilation(procedure.getRef());
|
||||
|
||||
// enter the procedure
|
||||
scopeStack.push(procedure);
|
||||
|
||||
// Add return variable
|
||||
Variable returnVar = null;
|
||||
if(!SymbolType.VOID.equals(type)) {
|
||||
final VariableBuilder builder = new VariableBuilder("return", procedure, false, varDecl.getEffectiveType(), varDecl.getDeclDirectives(), currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
|
||||
if(!SymbolType.VOID.equals(procedure.getReturnType())) {
|
||||
final VariableBuilder builder = new VariableBuilder("return", procedure, false, procedure.getReturnType(), varDecl.getDeclDirectives(), currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
|
||||
returnVar = builder.build();
|
||||
}
|
||||
varDecl.exitType();
|
||||
|
||||
// Add parameter variables...
|
||||
List<Variable> parameterList = new ArrayList<>();
|
||||
if(ctx.parameterListDecl() != null) {
|
||||
parameterList = (List<Variable>) this.visit(ctx.parameterListDecl());
|
||||
for(ParameterDecl parameter : varDecl.parameters) {
|
||||
VariableBuilder varBuilder = new VariableBuilder(parameter.name, getCurrentScope(), true, parameter.type, null, currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
|
||||
final Variable paramVar = varBuilder.build();
|
||||
parameterList.add(paramVar);
|
||||
}
|
||||
procedure.setParameters(parameterList);
|
||||
|
||||
varDecl.exitType();
|
||||
|
||||
// Check that the body has not already been added
|
||||
final StatementSequence statementSequence = getCurrentProcedureCompilation().getStatementSequence();
|
||||
if(statementSequence != null && statementSequence.getStatements().size() > 0)
|
||||
throw new CompileError("Redefinition of function: " + procedure.getFullName(), StatementSource.procedureBegin(ctx));
|
||||
|
||||
// Add the body
|
||||
addStatement(new StatementProcedureBegin(procedure.getRef(), StatementSource.procedureBegin(ctx), Comment.NO_COMMENTS));
|
||||
// Add parameter assignments
|
||||
if(Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) {
|
||||
for(Variable param : parameterList) {
|
||||
addStatement(new StatementAssignment((LValue) param.getRef(), new ParamValue((VariableRef) param.getRef()), true, StatementSource.procedureEnd(ctx), Comment.NO_COMMENTS));
|
||||
}
|
||||
}
|
||||
Label procExit = procedure.addLabel(SymbolRef.PROCEXIT_BLOCK_NAME);
|
||||
if(ctx.stmtSeq() != null) {
|
||||
this.visit(ctx.stmtSeq());
|
||||
}
|
||||
addStatement(new StatementLabel(procExit.getRef(), StatementSource.procedureEnd(ctx), Comment.NO_COMMENTS));
|
||||
if(Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention()) && returnVar != null) {
|
||||
addStatement(new StatementAssignment(returnVar.getVariableRef(), returnVar.getRef(), false, StatementSource.procedureEnd(ctx), Comment.NO_COMMENTS));
|
||||
}
|
||||
SymbolVariableRef returnVarRef = null;
|
||||
if(returnVar != null) {
|
||||
returnVarRef = returnVar.getRef();
|
||||
}
|
||||
addStatement(new StatementReturn(returnVarRef, StatementSource.procedureEnd(ctx), Comment.NO_COMMENTS));
|
||||
addStatement(new StatementProcedureEnd(procedure.getRef(), StatementSource.procedureEnd(ctx), Comment.NO_COMMENTS));
|
||||
scopeStack.pop();
|
||||
|
||||
// Check that the declaration matches any existing declaration!
|
||||
final Symbol existingSymbol = program.getScope().getSymbol(procedure.getRef());
|
||||
if(existingSymbol != null) {
|
||||
// Already declared - check equality
|
||||
if(!(existingSymbol instanceof Procedure) || !SymbolTypeConversion.procedureDeclarationMatch((Procedure) existingSymbol, procedure))
|
||||
throw new CompileError("Conflicting declarations for: " + procedure.getFullName(), new StatementSource(ctx));
|
||||
} else {
|
||||
// Not declared before - add it
|
||||
program.getScope().add(procedure);
|
||||
program.createProcedureCompilation(procedure.getRef());
|
||||
}
|
||||
|
||||
if(ctx.declFunctionBody() != null || VariableBuilder.hasDirective(Directive.Intrinsic.class, directives)) {
|
||||
// Make sure directives and more are taken from the procedure with the body / intrinsic declaration!
|
||||
if(existingSymbol != null) {
|
||||
program.getScope().remove(existingSymbol);
|
||||
program.getScope().add(procedure);
|
||||
}
|
||||
}
|
||||
|
||||
if(ctx.declFunctionBody() != null) {
|
||||
scopeStack.push(procedure);
|
||||
// Check that the body has not already been added
|
||||
final StatementSequence statementSequence = getCurrentProcedureCompilation().getStatementSequence();
|
||||
if(statementSequence != null && statementSequence.getStatements().size() > 0)
|
||||
throw new CompileError("Redefinition of function: " + procedure.getFullName(), StatementSource.procedureBegin(ctx));
|
||||
// Add the body
|
||||
addStatement(new StatementProcedureBegin(procedure.getRef(), StatementSource.procedureBegin(ctx), Comment.NO_COMMENTS));
|
||||
// Add parameter assignments
|
||||
if(Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) {
|
||||
for(Variable param : parameterList) {
|
||||
addStatement(new StatementAssignment((LValue) param.getRef(), new ParamValue((VariableRef) param.getRef()), true, StatementSource.procedureEnd(ctx), Comment.NO_COMMENTS));
|
||||
}
|
||||
}
|
||||
Label procExit = procedure.addLabel(SymbolRef.PROCEXIT_BLOCK_NAME);
|
||||
if(ctx.declFunctionBody().stmtSeq() != null) {
|
||||
this.visit(ctx.declFunctionBody().stmtSeq());
|
||||
}
|
||||
addStatement(new StatementLabel(procExit.getRef(), StatementSource.procedureEnd(ctx), Comment.NO_COMMENTS));
|
||||
if(Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention()) && returnVar != null) {
|
||||
addStatement(new StatementAssignment(returnVar.getVariableRef(), returnVar.getRef(), false, StatementSource.procedureEnd(ctx), Comment.NO_COMMENTS));
|
||||
}
|
||||
SymbolVariableRef returnVarRef = null;
|
||||
if(returnVar != null) {
|
||||
returnVarRef = returnVar.getRef();
|
||||
}
|
||||
addStatement(new StatementReturn(returnVarRef, StatementSource.procedureEnd(ctx), Comment.NO_COMMENTS));
|
||||
addStatement(new StatementProcedureEnd(procedure.getRef(), StatementSource.procedureEnd(ctx), Comment.NO_COMMENTS));
|
||||
scopeStack.pop();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Variable> visitParameterListDecl(KickCParser.ParameterListDeclContext ctx) {
|
||||
/*
|
||||
ArrayList<Variable> parameterDecls = new ArrayList<>();
|
||||
boolean encounteredVariableLengthParamList = false;
|
||||
for(KickCParser.ParameterDeclContext parameterDeclCtx : ctx.parameterDecl()) {
|
||||
@ -494,17 +481,18 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
}
|
||||
}
|
||||
return parameterDecls;
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object visitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) {
|
||||
this.visit(ctx.declType());
|
||||
this.visit(ctx.declarator());
|
||||
String varName = varDecl.getVarName();
|
||||
VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), true, varDecl.getEffectiveType(), varDecl.getDeclDirectives(), currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
|
||||
Variable param = varBuilder.build();
|
||||
ParameterDecl paramDecl = new ParameterDecl(varDecl.getVarName(), varDecl.getEffectiveType());
|
||||
varDecl.exitType();
|
||||
return param;
|
||||
return paramDecl;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -512,15 +500,12 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
if(!SymbolType.VOID.getTypeName().equals(ctx.SIMPLETYPE().getText())) {
|
||||
throw new CompileError("Illegal unnamed parameter " + ctx.SIMPLETYPE().getText(), new StatementSource(ctx));
|
||||
}
|
||||
return SymbolType.VOID;
|
||||
return new ParameterDecl(null, SymbolType.VOID);
|
||||
}
|
||||
|
||||
/** Singleton signalling a "..." parameter list. */
|
||||
public static Object PARAM_LIST = new Object();
|
||||
|
||||
@Override
|
||||
public Object visitParameterDeclList(KickCParser.ParameterDeclListContext ctx) {
|
||||
return PARAM_LIST;
|
||||
return new ParameterDecl(null, SymbolType.PARAM_LIST);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -740,13 +725,26 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
return new AsmDirectiveClobber(clobber);
|
||||
}
|
||||
|
||||
|
||||
/** Information about a declared parameter. */
|
||||
static class ParameterDecl {
|
||||
final public String name;
|
||||
final public SymbolType type;
|
||||
|
||||
public ParameterDecl(String name, SymbolType type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Holds type, arrayness, directives, comments etc. while parsing a variable declaration.
|
||||
* Holds type directives, comments etc. while parsing a variable or procedure declaration.
|
||||
* Has three levels of information pushed on top of each other:
|
||||
* <ol>
|
||||
* <li>Struct Member Declaration (true while inside inside a struct declaration)</li>
|
||||
* <li>Type information and directives (the type)</li>
|
||||
* <li>Variable information and declarations (arrayness, pointerness, variable level directives)</li>
|
||||
* <li>Information about parameters (for procedures)</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* When parsing a declaration such as <code>volatile char a, * const b, c[]</code> the type level holds <code>volatile char</code>
|
||||
@ -766,6 +764,8 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
private SymbolType varDeclType;
|
||||
/** The variable name (variable level) */
|
||||
private String varName;
|
||||
/** The declared parameters (if this is a procedure). */
|
||||
private List<ParameterDecl> parameters;
|
||||
|
||||
/**
|
||||
* Exits the type layer (clears everything except struct information)
|
||||
@ -776,6 +776,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
this.declType = null;
|
||||
this.varDeclType = null;
|
||||
this.varName = null;
|
||||
this.parameters = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -784,6 +785,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
void exitVar() {
|
||||
this.varDeclType = null;
|
||||
this.varName = null;
|
||||
this.parameters = new ArrayList<>();
|
||||
}
|
||||
|
||||
SymbolType getEffectiveType() {
|
||||
@ -862,6 +864,14 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
this.structMember = structMember;
|
||||
}
|
||||
|
||||
public void setParameters(List<ParameterDecl> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public List<ParameterDecl> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** The current variable declaration. This is not on the stack. */
|
||||
@ -923,48 +933,57 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
String varName = varDecl.getVarName();
|
||||
KickCParser.ExprContext initializer = ctx.expr();
|
||||
StatementSource declSource = new StatementSource((ParserRuleContext) ctx.parent.parent);
|
||||
StatementSource statementSource = declSource;
|
||||
try {
|
||||
final boolean isStructMember = varDecl.isStructMember();
|
||||
final SymbolType effectiveType = varDecl.getEffectiveType();
|
||||
final List<Directive> effectiveDirectives = varDecl.getDeclDirectives();
|
||||
final List<Comment> declComments = varDecl.getDeclComments();
|
||||
varDecl.exitVar();
|
||||
VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), false, effectiveType, effectiveDirectives, currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
|
||||
Variable variable = varBuilder.build();
|
||||
if(isStructMember && (initializer != null))
|
||||
throw new CompileError("Initializer not supported inside structs " + effectiveType.getTypeName(), statementSource);
|
||||
if(variable.isDeclarationOnly()) {
|
||||
if(initializer != null) {
|
||||
throw new CompileError("Initializer not allowed for extern variables " + varName, statementSource);
|
||||
}
|
||||
} else {
|
||||
// Create a proper initializer
|
||||
if(initializer != null)
|
||||
PrePostModifierHandler.addPreModifiers(this, initializer, statementSource);
|
||||
RValue initValue = (initializer == null) ? null : (RValue) visit(initializer);
|
||||
initValue = Initializers.constantify(initValue, new Initializers.ValueTypeSpec(effectiveType), program, statementSource);
|
||||
boolean isPermanent = ScopeRef.ROOT.equals(variable.getScope().getRef()) || variable.isPermanent();
|
||||
if(variable.isKindConstant() || (isPermanent && variable.isKindLoadStore() && Variable.MemoryArea.MAIN_MEMORY.equals(variable.getMemoryArea()) && initValue instanceof ConstantValue && !isStructMember && variable.getRegister() == null)) {
|
||||
// Set initial value
|
||||
ConstantValue constInitValue = getConstInitValue(initValue, initializer, statementSource);
|
||||
variable.setInitValue(constInitValue);
|
||||
// Add comments to constant
|
||||
variable.setComments(ensureUnusedComments(declComments));
|
||||
} else if(!variable.isKindConstant() && !isStructMember) {
|
||||
Statement initStmt = new StatementAssignment(variable.getVariableRef(), initValue, true, statementSource, Comment.NO_COMMENTS);
|
||||
addStatement(initStmt);
|
||||
if(variable.getScope().getRef().equals(ScopeRef.ROOT)) {
|
||||
// Add comments to variable for global vars
|
||||
variable.setComments(ensureUnusedComments(declComments));
|
||||
} else {
|
||||
// Add comments to statement for local vars
|
||||
initStmt.setComments(ensureUnusedComments(declComments));
|
||||
}
|
||||
|
||||
if(effectiveType instanceof SymbolTypeProcedure) {
|
||||
Procedure procedure = new Procedure(varName, (SymbolTypeProcedure) effectiveType, program.getScope(), currentCodeSegment, currentDataSegment, currentCallingConvention);
|
||||
addDirectives(procedure, effectiveDirectives, declSource);
|
||||
procedure.setComments(ensureUnusedComments(getCommentsSymbol(ctx)));
|
||||
// TODO: Detect existing declarations and check for match!
|
||||
program.getScope().add(procedure);
|
||||
program.createProcedureCompilation(procedure.getRef());
|
||||
} else {
|
||||
VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), false, effectiveType, effectiveDirectives, currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
|
||||
Variable variable = varBuilder.build();
|
||||
if(isStructMember && (initializer != null))
|
||||
throw new CompileError("Initializer not supported inside structs " + effectiveType.getTypeName(), declSource);
|
||||
if(variable.isDeclarationOnly()) {
|
||||
if(initializer != null) {
|
||||
throw new CompileError("Initializer not allowed for extern variables " + varName, declSource);
|
||||
}
|
||||
} else {
|
||||
// Create a proper initializer
|
||||
if(initializer != null)
|
||||
PrePostModifierHandler.addPreModifiers(this, initializer, declSource);
|
||||
RValue initValue = (initializer == null) ? null : (RValue) visit(initializer);
|
||||
initValue = Initializers.constantify(initValue, new Initializers.ValueTypeSpec(effectiveType), program, declSource);
|
||||
boolean isPermanent = ScopeRef.ROOT.equals(variable.getScope().getRef()) || variable.isPermanent();
|
||||
if(variable.isKindConstant() || (isPermanent && variable.isKindLoadStore() && Variable.MemoryArea.MAIN_MEMORY.equals(variable.getMemoryArea()) && initValue instanceof ConstantValue && !isStructMember && variable.getRegister() == null)) {
|
||||
// Set initial value
|
||||
ConstantValue constInitValue = getConstInitValue(initValue, initializer, declSource);
|
||||
variable.setInitValue(constInitValue);
|
||||
// Add comments to constant
|
||||
variable.setComments(ensureUnusedComments(declComments));
|
||||
} else if(!variable.isKindConstant() && !isStructMember) {
|
||||
Statement initStmt = new StatementAssignment(variable.getVariableRef(), initValue, true, declSource, Comment.NO_COMMENTS);
|
||||
addStatement(initStmt);
|
||||
if(variable.getScope().getRef().equals(ScopeRef.ROOT)) {
|
||||
// Add comments to variable for global vars
|
||||
variable.setComments(ensureUnusedComments(declComments));
|
||||
} else {
|
||||
// Add comments to statement for local vars
|
||||
initStmt.setComments(ensureUnusedComments(declComments));
|
||||
}
|
||||
|
||||
}
|
||||
if(initializer != null)
|
||||
PrePostModifierHandler.addPostModifiers(this, initializer, declSource);
|
||||
}
|
||||
if(initializer != null)
|
||||
PrePostModifierHandler.addPostModifiers(this, initializer, statementSource);
|
||||
}
|
||||
} catch(CompileError e) {
|
||||
throw new CompileError(e.getMessage(), declSource);
|
||||
@ -1950,16 +1969,24 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
public Object visitDeclaratorProcedure(KickCParser.DeclaratorProcedureContext ctx) {
|
||||
visit(ctx.declarator());
|
||||
// TODO: Handle parameters!
|
||||
List<ParameterDecl> parameters = new ArrayList<>();
|
||||
List<SymbolType> paramTypes = new ArrayList<>();
|
||||
if(ctx.parameterListDecl() != null)
|
||||
for(KickCParser.ParameterDeclContext parameterDeclContext : ctx.parameterListDecl().parameterDecl()) {
|
||||
varDeclPush();
|
||||
ParameterDecl paramDecl = (ParameterDecl) this.visit(parameterDeclContext);
|
||||
paramTypes.add(paramDecl.type);
|
||||
parameters.add(paramDecl);
|
||||
varDeclPop();
|
||||
}
|
||||
SymbolType returnType = varDecl.getEffectiveType();
|
||||
varDecl.setDeclType(new SymbolTypeProcedure(returnType));
|
||||
varDecl.setDeclType(new SymbolTypeProcedure(returnType, paramTypes));
|
||||
varDecl.setParameters(parameters);
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Object visitTypeNamedRef(KickCParser.TypeNamedRefContext ctx) {
|
||||
@ -2004,14 +2031,6 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitTypeProcedure(KickCParser.TypeProcedureContext ctx) {
|
||||
visit(ctx.type());
|
||||
SymbolType returnType = varDecl.getEffectiveType();
|
||||
varDecl.setDeclType(new SymbolTypeProcedure(returnType));
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* RValues that have not yet been output as part of a statement.
|
||||
* The expression visitor methods updates this so that the surrounding
|
||||
|
@ -9,9 +9,44 @@ import java.io.IOException;
|
||||
*/
|
||||
public class TestProgramsFast extends TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testProcedureDeclare7() throws IOException {
|
||||
compileAndCompare("procedure-declare-7.c", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcedureDeclare6() throws IOException {
|
||||
compileAndCompare("procedure-declare-6.c", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcedureDeclare5() throws IOException {
|
||||
compileAndCompare("procedure-declare-5.c", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcedureDeclare4() throws IOException {
|
||||
compileAndCompare("procedure-declare-4.c", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcedureDeclare3() throws IOException {
|
||||
compileAndCompare("procedure-declare-3.c", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcedureDeclare2() throws IOException {
|
||||
compileAndCompare("procedure-declare-2.c", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcedureDeclare1() throws IOException {
|
||||
compileAndCompare("procedure-declare-1.c", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcedureDeclare0() throws IOException {
|
||||
compileAndCompare("procedure-declare-0.c");
|
||||
compileAndCompare("procedure-declare-0.c", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,13 +1,7 @@
|
||||
// Procedure Declaration
|
||||
|
||||
char f(char a);
|
||||
// Procedure Declaration - a single procedure without parameters declared and defined at once
|
||||
|
||||
void main() {
|
||||
char * const SCREEN = 0x0400;
|
||||
SCREEN[0] = f('a');
|
||||
SCREEN[1] = f('b');
|
||||
SCREEN[0] = 'a';
|
||||
}
|
||||
|
||||
char f(char a) {
|
||||
return a+1;
|
||||
}
|
||||
|
9
src/test/kc/procedure-declare-1.c
Normal file
9
src/test/kc/procedure-declare-1.c
Normal file
@ -0,0 +1,9 @@
|
||||
// Procedure Declaration - A single procedure without parameters or return declared and then defined
|
||||
|
||||
void main();
|
||||
|
||||
void main() {
|
||||
char * const SCREEN = 0x0400;
|
||||
SCREEN[0] = 'a';
|
||||
}
|
||||
|
11
src/test/kc/procedure-declare-2.c
Normal file
11
src/test/kc/procedure-declare-2.c
Normal file
@ -0,0 +1,11 @@
|
||||
// Procedure Declaration - a procedure with paramters&return defined without declaration
|
||||
|
||||
char sum(char a, char b) {
|
||||
return a+b+1;
|
||||
}
|
||||
|
||||
void main() {
|
||||
char * const SCREEN = 0x0400;
|
||||
SCREEN[0] = f('a', 1);
|
||||
SCREEN[1] = f('b', 2);
|
||||
}
|
14
src/test/kc/procedure-declare-3.c
Normal file
14
src/test/kc/procedure-declare-3.c
Normal file
@ -0,0 +1,14 @@
|
||||
// Procedure Declaration - a procedure with paramters&return declared & defined
|
||||
|
||||
char sum(char a, char b);
|
||||
|
||||
void main() {
|
||||
char * const SCREEN = 0x0400;
|
||||
SCREEN[0] = f('a', 1);
|
||||
SCREEN[1] = f('b', 2);
|
||||
}
|
||||
|
||||
char sum(char a, char b) {
|
||||
return a+b+1;
|
||||
}
|
||||
|
19
src/test/kc/procedure-declare-4.c
Normal file
19
src/test/kc/procedure-declare-4.c
Normal file
@ -0,0 +1,19 @@
|
||||
// Procedure Declaration - a procedure with paramters&return declared multiple times & defined
|
||||
|
||||
char sum(char a, char b);
|
||||
|
||||
void main() {
|
||||
char * const SCREEN = 0x0400;
|
||||
SCREEN[0] = f('a', 1);
|
||||
SCREEN[1] = f('b', 2);
|
||||
}
|
||||
|
||||
char sum(char x, char y);
|
||||
|
||||
char sum(char q, char w) {
|
||||
return q+w+1;
|
||||
}
|
||||
|
||||
char sum(char z, char r);
|
||||
|
||||
|
13
src/test/kc/procedure-declare-5.c
Normal file
13
src/test/kc/procedure-declare-5.c
Normal file
@ -0,0 +1,13 @@
|
||||
// Procedure Declaration - a void procedure declared with empty parenthesis
|
||||
|
||||
char f(void);
|
||||
|
||||
char f() {
|
||||
return 7;
|
||||
}
|
||||
|
||||
void main() {
|
||||
char * const SCREEN = 0x0400;
|
||||
SCREEN[0] = f();
|
||||
}
|
||||
|
14
src/test/kc/procedure-declare-6.c
Normal file
14
src/test/kc/procedure-declare-6.c
Normal file
@ -0,0 +1,14 @@
|
||||
// Procedure Declaration - declaration and definition mismatch of a procedure
|
||||
|
||||
char f(char a);
|
||||
|
||||
int f(char a) {
|
||||
return a+1;
|
||||
}
|
||||
|
||||
void main() {
|
||||
int * const SCREEN = 0x0400;
|
||||
SCREEN[0] = f('a');
|
||||
SCREEN[1] = f('b');
|
||||
}
|
||||
|
17
src/test/kc/procedure-declare-7.c
Normal file
17
src/test/kc/procedure-declare-7.c
Normal file
@ -0,0 +1,17 @@
|
||||
// Procedure Declaration - two declarations mismatch of a procedure
|
||||
|
||||
char f(char a);
|
||||
|
||||
int f(char a);
|
||||
|
||||
void main() {
|
||||
char * const SCREEN = 0x0400;
|
||||
SCREEN[0] = f('a');
|
||||
SCREEN[1] = f('b');
|
||||
}
|
||||
|
||||
char f(char a) {
|
||||
return a+1;
|
||||
}
|
||||
|
||||
|
20
src/test/kc/procedure-declare-8.c
Normal file
20
src/test/kc/procedure-declare-8.c
Normal file
@ -0,0 +1,20 @@
|
||||
// Procedure Declaration
|
||||
|
||||
char f(char a);
|
||||
|
||||
void g();
|
||||
|
||||
void h(void);
|
||||
|
||||
//void i(char a, ...);
|
||||
|
||||
char f(char a) {
|
||||
return a+1;
|
||||
}
|
||||
|
||||
void main() {
|
||||
char * const SCREEN = 0x0400;
|
||||
SCREEN[0] = f('a');
|
||||
SCREEN[1] = f('b');
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user