Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions examples/snake/snake.tile
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@ import "../tileraylib.tile";
screenWidth: int = 400;
screenHeight: int = screenWidth;

func run_game(): void {

prev_dirs: int[] = int[50];
posx: float[] = float[50];
posy: float[] = float[50];
dirs: int[] = int[50];
prev_dirs: int[] = int[50];
posx: float[] = float[50];
posy: float[] = float[50];
dirs: int[] = int[50];
snake_count: int = 1;

func is_tile_empty(cherry_posx: float, cherry_posy: float): bool {
for (i: int = 0; i < snake_count; i++) {
if ((int)cherry_posx == (int)posx[i] && (int)cherry_posy == (int)posy[i]) {
return false;
}
}
return true;
}

snake_count: int = 1;
func run_game(): void {
snake_step: int = screenWidth / 10;
snake_size: int = snake_step;

Expand Down Expand Up @@ -111,6 +119,11 @@ func run_game(): void {
// randomly put the cherry again
cherry_posx = GetRandomValue(0, 9) * snake_size;
cherry_posy = GetRandomValue(0, 9) * snake_size;
// do not allow cherry to be appeared under snake!
while (!is_tile_empty(cherry_posx, cherry_posy)) {
cherry_posx = GetRandomValue(0, 9) * snake_size;
cherry_posy = GetRandomValue(0, 9) * snake_size;
}
}
}

Expand Down Expand Up @@ -151,7 +164,7 @@ func main(argc: int): void {
InitWindow(screenWidth, screenHeight, "Snake Game");
SetTargetFPS(60); // Set our game to run at 60 frames-per-second

SetRandomSeed(4642);
SetRandomSeed(GetTime() * 100);

run_game();

Expand Down
1 change: 1 addition & 0 deletions examples/tileraylib.tile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ native func EndDrawing(): cvoid;
native func ClearBackground(color: cu32): cvoid;
native func SetTargetFPS(fps: ci32): cvoid;
native func GetFrameTime(): cf32;
native func GetTime(): cf64;
native func DrawRectangle(posX: ci32, posY: ci32, width: ci32, height: ci32, color: cu32): cvoid;
native func DrawCircle(posX: ci32, posY: ci32, radius: cf32, color: cu32): cvoid;
native func DrawLine(ci32, ci32, ci32, ci32, cu32): cvoid;
Expand Down
113 changes: 113 additions & 0 deletions src/tile/AntlrToExpression.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import gen.antlr.tile.tileParser.LogicalAndExpressionContext;
import gen.antlr.tile.tileParser.LogicalOrExpressionContext;
import gen.antlr.tile.tileParser.MultiplicativeExpressionContext;
import gen.antlr.tile.tileParser.ObjectAccessorContext;
import gen.antlr.tile.tileParser.ObjectLiteralExpressionContext;
import gen.antlr.tile.tileParser.PrimaryExpressionContext;
import gen.antlr.tile.tileParser.RelationalExpressionContext;
import gen.antlr.tile.tileParser.ShiftExpressionContext;
Expand All @@ -40,10 +42,13 @@
import tile.ast.expr.FuncCallExpression;
import tile.ast.expr.LogicalExpression;
import tile.ast.expr.MultiplicativeExpression;
import tile.ast.expr.ObjectAccessor;
import tile.ast.expr.ObjectLiteral;
import tile.ast.expr.PrimaryExpression;
import tile.ast.expr.RelationalExpression;
import tile.ast.expr.ShiftExpression;
import tile.ast.expr.UnaryExpression;
import tile.ast.stmt.TypeDefinition;
import tile.ast.types.TypeResolver;
import tile.ast.types.TypeResolver.TypeFuncCall;
import tile.ast.types.TypeResolver.TypeInfoArray;
Expand Down Expand Up @@ -463,6 +468,10 @@ public Expression visitUnaryExpression(UnaryExpressionContext ctx) {
if (!(type.equals("int") || type.equals("float"))) {
Log.error("'+' and '-' prefixes cannot go before any non-numeric type!");
}
} else if (unaryOp.equals("!")) {
if (!type.equals("bool")) {
Log.error("'" + unaryOp + "' operator cannot go before this type: " + type);
}
}
}
else if (ctx.incDecOperator() != null) {
Expand Down Expand Up @@ -573,4 +582,108 @@ public Expression visitForUpdate(ForUpdateContext ctx) {
return result;
}

@Override
public Expression visitObjectLiteralExpression(ObjectLiteralExpressionContext ctx) {
String type = "";
if (ctx.IDENTIFIER() != null) {
// Implemented
/*
a: Animal = Animal {
.name = "asd",
.age = 10
};
*/
type = ctx.IDENTIFIER().getText();
TypeDefinition td = TypeResolver.userTypeDefs.get(type);
if (td == null) {
int line = ctx.IDENTIFIER().getSymbol().getLine();
int col = ctx.IDENTIFIER().getSymbol().getCharPositionInLine();
Log.error(line + ":" + col + ": literal type " + type + " cannot be resolved!");
} else {
// traverse {.identifier} and typedefinition fields to see if they matched
if (ctx.objectLiteralFieldAssignment() != null) {
int[] assignedFields = new int[td.getFields().size()];
for (int i = 0; i < ctx.objectLiteralFieldAssignment().size(); i++) {
String objLitFieldId = ctx.objectLiteralFieldAssignment(i).IDENTIFIER().getText();

if (td.getFields().get(objLitFieldId) == null) {
int line = ctx.objectLiteralFieldAssignment(i).IDENTIFIER().getSymbol().getLine();
int col = ctx.objectLiteralFieldAssignment(i).IDENTIFIER().getSymbol().getCharPositionInLine();
Log.error(line + ":" + col + ": " + type + " doesn't have a field " + objLitFieldId + "!");
}
}

ObjectLiteral objLit = new ObjectLiteral(td, type, assignedFields);
return objLit;
}
}

} else {
// TODO: Not implemented inferring type
/*
a: Animal = {0};
a: Animal = {
.name = "asd",
.age = 10
};
*/
int line = ctx.PUNC_LEFTBRACE().getSymbol().getLine();
int col = ctx.PUNC_LEFTBRACE().getSymbol().getCharPositionInLine();
Log.error(line + ":" + col + ": for custom literal type, type inferring is not implemented yet!");
}



return super.visitObjectLiteralExpression(ctx);
}

@Override
public Expression visitObjectAccessor(ObjectAccessorContext ctx) {
String identifier = ctx.IDENTIFIER(0).getText();
StringBuilder varType = new StringBuilder();
int tasmIdx = -1;
AtomicBoolean isGlobal = new AtomicBoolean(false);
try {
tasmIdx = TasmSymbolGenerator.identifierScopeFind(identifier, varType, isGlobal);
// TODO: use isGlobal!!!
} catch (Exception e) {
int line = ctx.IDENTIFIER(0).getSymbol().getLine();
int col = ctx.IDENTIFIER(0).getSymbol().getCharPositionInLine();
Log.error(line + ":" + col + ": variable " + "'" + identifier + "' is not defined before use!");
}

String type = varType.toString();
TypeDefinition td = TypeResolver.userTypeDefs.get(type);


if (ctx.objectAccessor() == null) {
String fieldId = ctx.IDENTIFIER(1).getText();
if (td != null) {
td.getFields().get(fieldId);
if (td.getFields().get(fieldId) == null) {
int line = ctx.IDENTIFIER(1).getSymbol().getLine();
int col = ctx.IDENTIFIER(1).getSymbol().getCharPositionInLine();
Log.error(line + ":" + col + ": '" + identifier + ": " + type + "'' doesn't have a field " + fieldId + "!");
}
}

ObjectAccessor oa = new ObjectAccessor(fieldId, td, tasmIdx, null);
if (isGlobal.get() == true) {
oa.setAsGlobal();
}

return oa;
} else {

ObjectAccessor accessor = (ObjectAccessor)visit(ctx.objectAccessor());

ObjectAccessor oa = new ObjectAccessor(null, td, tasmIdx, accessor);
if (isGlobal.get() == true) {
oa.setAsGlobal();
}

return oa;
}
}

}
63 changes: 58 additions & 5 deletions src/tile/AntlrToStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
Expand All @@ -21,6 +22,7 @@
import gen.antlr.tile.tileParser.LoopStmtContext;
import gen.antlr.tile.tileParser.ImportStmtContext;
import gen.antlr.tile.tileParser.NativeFuncDeclStmtContext;
import gen.antlr.tile.tileParser.ObjectAccessorContext;
import gen.antlr.tile.tileParser.ProgramContext;
import gen.antlr.tile.tileParser.ReturnStmtContext;
import gen.antlr.tile.tileParser.SelectionStmtContext;
Expand Down Expand Up @@ -306,16 +308,25 @@ else if (ctx.variableStmt() != null) {
@Override
public Statement visitTypeDefinition(TypeDefinitionContext ctx) {
String typeName = ctx.IDENTIFIER().getText();
List<TypeDefinition.Field> fields = null;
HashMap<String, TypeDefinition.Field> fields = null;
TypeDefinition.Kind kind = null;
if (ctx.structDefinition() != null) {
fields = new ArrayList<>();
fields = new HashMap<>();
kind = TypeDefinition.Kind.STRUCT;
int offset = 0;
for (int i = 0; i < ctx.structDefinition().fieldDefinition().size(); i++) {
String id = ctx.structDefinition().fieldDefinition(i).IDENTIFIER().getText();
String type = ctx.structDefinition().fieldDefinition(i).typeName().getText();
TypeDefinition.Field field = new TypeDefinition.Field(id, type);
fields.add(field);
int type_size = TypeResolver.resolveFieldTypeSize(type);
TypeDefinition.Field field = new TypeDefinition.Field(id, type, type_size, offset);
offset += type_size;
if (!fields.containsKey(id)) {
fields.put(id, field);
} else {
int line = ctx.structDefinition().fieldDefinition(i).IDENTIFIER().getSymbol().getLine();
int col = ctx.structDefinition().fieldDefinition(i).IDENTIFIER().getSymbol().getCharPositionInLine();
Log.error(line + ":" + col + " " + id + " field is already defined in " + typeName + "!");
}
}
}

Expand Down Expand Up @@ -458,8 +469,21 @@ public Statement visitWhileStmt(WhileStmtContext ctx) {
@Override
public Statement visitVariableAssignment(VariableAssignmentContext ctx) {
String varId = "";
List<String> fieldIds = new ArrayList<>();
if (ctx.arrayIndexAccessorSetter() != null) {
varId = ctx.arrayIndexAccessorSetter().IDENTIFIER().getText();
} else if (ctx.objectAccessor() != null) {
varId = ctx.objectAccessor().IDENTIFIER(0).getText();
ObjectAccessorContext oac = ctx.objectAccessor();
if (oac.IDENTIFIER(1) != null) {
fieldIds.add(oac.IDENTIFIER(1).getText());
}
while (oac.objectAccessor() != null) {
oac = oac.objectAccessor();
fieldIds.add(oac.IDENTIFIER(0).getText());
}

Log.debug(fieldIds.toString());
} else {
varId = ctx.IDENTIFIER().getText();
}
Expand All @@ -476,6 +500,9 @@ public Statement visitVariableAssignment(VariableAssignmentContext ctx) {
if (ctx.arrayIndexAccessorSetter() != null) {
line = ctx.arrayIndexAccessorSetter().IDENTIFIER().getSymbol().getLine();
col = ctx.arrayIndexAccessorSetter().IDENTIFIER().getSymbol().getCharPositionInLine();
} else if (ctx.objectAccessor() != null) {
line = ctx.objectAccessor().IDENTIFIER(0).getSymbol().getLine();
col = ctx.objectAccessor().IDENTIFIER(0).getSymbol().getCharPositionInLine();
} else {
line = ctx.IDENTIFIER().getSymbol().getLine();
col = ctx.IDENTIFIER().getSymbol().getCharPositionInLine();
Expand Down Expand Up @@ -508,6 +535,8 @@ public Statement visitVariableAssignment(VariableAssignmentContext ctx) {
exprs.add(expr);
}
typeInfo = TypeResolver.resolveVariableDefArrayType(varTypeStr, exprType, dim);
} else if (ctx.objectAccessor() != null) {
typeInfo = TypeResolver.resolveVariableDefUserDefType(varTypeStr, exprType, fieldIds);
} else {
typeInfo = TypeResolver.resolveVariableDefType(varTypeStr, exprType);
}
Expand All @@ -522,13 +551,24 @@ public Statement visitVariableAssignment(VariableAssignmentContext ctx) {

@Override
public Statement visitVariableDecleration(VariableDeclerationContext ctx) {
// TODO Auto-generated method stub
// int a;
// Cat b;

String type = ctx.typeName().getText();
String varId = ctx.IDENTIFIER().getText();

if (ctx.typeName().primaryTypeName() != null) {
if (ctx.typeName().primaryTypeName().IDENTIFIER() != null) {
TypeDefinition td = TypeResolver.userTypeDefs.get(type);

if (td == null) {
int line = ctx.typeName().primaryTypeName().IDENTIFIER().getSymbol().getLine();
int col = ctx.typeName().primaryTypeName().IDENTIFIER().getSymbol().getCharPositionInLine();
Log.error(line + ":" + col + ": type " + type + " cannot be resolved!");
}
}
}

VariableDecleration v_dec = new VariableDecleration(type, varId);

// if it is global
Expand All @@ -545,6 +585,19 @@ public Statement visitVariableDecleration(VariableDeclerationContext ctx) {
public Statement visitVariableDefinition(VariableDefinitionContext ctx) {
String type = ctx.typeName().getText();
String varId = ctx.IDENTIFIER().getText();

if (ctx.typeName().primaryTypeName() != null) {
if (ctx.typeName().primaryTypeName().IDENTIFIER() != null) {
TypeDefinition td = TypeResolver.userTypeDefs.get(type);

if (td == null) {
int line = ctx.typeName().primaryTypeName().IDENTIFIER().getSymbol().getLine();
int col = ctx.typeName().primaryTypeName().IDENTIFIER().getSymbol().getCharPositionInLine();
Log.error(line + ":" + col + ": type " + type + " cannot be resolved!");
}
}
}

Statement exprStmt = visit(ctx.expressionStmt());

String exprType = ((ExpressionStmt)exprStmt).getType();
Expand Down
50 changes: 50 additions & 0 deletions src/tile/ast/expr/ObjectAccessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package tile.ast.expr;

import tile.ast.base.Expression;
import tile.ast.stmt.TypeDefinition;

public class ObjectAccessor implements Expression {
private TypeDefinition typeDefinition;
private int identifierTasmIdx;
boolean isGlobal = false;
private String fieldId;
ObjectAccessor accessor;

public void setAsGlobal() {
this.isGlobal = true;
}

public ObjectAccessor(String fieldId, TypeDefinition typeDefinition, int identifierTasmIdx, ObjectAccessor accessor) {
this.identifierTasmIdx = identifierTasmIdx;
this.accessor = accessor;
this.typeDefinition = typeDefinition;
this.fieldId = fieldId;
}

private String genLoadCode(String generatedCode) {
if (isGlobal) {
generatedCode += " gload " + identifierTasmIdx + "\n";
} else {
generatedCode += " load " + identifierTasmIdx + "\n";
}
return generatedCode;
}

@Override
public String generateTasm(String generatedCode) {
int size = typeDefinition.getFields().get(fieldId).type_size;
int offset = typeDefinition.getFields().get(fieldId).offset;

generatedCode = genLoadCode(generatedCode);
generatedCode += " deref ; dereferance\n";
generatedCode += " push " + offset + "\n";
generatedCode += " add\n";
generatedCode += " derefb " + size + " ; dereferance\n";
return generatedCode;
}

@Override
public String getType() {
return typeDefinition.getFields().get(fieldId).type;
}
}
Loading