Skip to content

Commit

Permalink
Work on field access expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyfa committed Mar 16, 2024
1 parent 648da5a commit d54b8d9
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 19 deletions.
11 changes: 5 additions & 6 deletions src/cscompiler/ast/CSExpr.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cscompiler.ast;

import cscompiler.ast.CSTypePath;
#if (macro || cs_runtime)

import haxe.macro.Expr;
Expand All @@ -11,7 +12,7 @@ import haxe.macro.Type;
@:structInit
class CSExpr {
public var def(default, null): CSExprDef;
public var haxeExpr(default, null): Null<TypedExpr>;
public var haxeExpr(default, null): Null<TypedExpr> = null;

public function new(def: CSExprDef, haxeExpr: Null<TypedExpr> = null) {
this.def = def;
Expand Down Expand Up @@ -41,15 +42,13 @@ enum CSExprDef {
/**
Binary operator `leftExpr op rightExpr`.
**/
// TODO Binop to CSBinop (because some operators are not supported by C#)
CSBinop(op: Binop, leftExpr: CSExpr, rightExpr: CSExpr);

/**
Field access on `e` of name `fieldName`.
TODO:
Replace `fieldName: String` with a custom `FieldAccess` type (`fieldAccess: CSFieldAccess`)?
**/
CSField(e: CSExpr, fieldName: String);
CSField(e: CSExpr, fieldAccess: CSFieldAccess);

/**
Reference to a module type `m`.
Expand All @@ -58,7 +57,7 @@ enum CSExprDef {
This is assuming static-access is only possible from a class in C#?
Maybe this should be replaced with a `CSStaticVar(varData: CSVar, cls: CSClass)`.
**/
CSClassExpr(cls: CSClass);
CSClassExpr(cls: CSTypePath);

/**
Parentheses `(e)`.
Expand Down
19 changes: 19 additions & 0 deletions src/cscompiler/ast/CSFieldAccess.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cscompiler.ast;

import cscompiler.ast.CSTypePath;

enum CSFieldAccess {

/**
Access of field `cf` on a class instance `c` with type parameters
`params`.
**/
CSFInstance(c:CSTypePath, params:Array<CSType>, cf:String);

/**
Static access of a field `cf` on a class `c`.
Note that we accept type params here because it is valid in C#
**/
CSFStatic(c:CSTypePath, params:Array<CSType>, cf:String);

}
2 changes: 1 addition & 1 deletion src/cscompiler/ast/CSStatement.hx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import haxe.macro.Type;
@:structInit
class CSStatement {
public var def(default, null): CSStatementDef;
public var haxeExpr(default, null): Null<TypedExpr>;
public var haxeExpr(default, null): Null<TypedExpr> = null;

public function new(def: CSStatementDef, haxeExpr: Null<TypedExpr> = null) {
this.def = def;
Expand Down
89 changes: 79 additions & 10 deletions src/cscompiler/components/CSCompiler_Expr.hx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class CSCompiler_Expr extends CSCompiler_Base {
haxeExpr: expr,
def: CSExprStatement({
haxeExpr: expr,
def: compileConstant(constant)
def: CSConst(compileConstant(constant))
})
}
case TLocal(v): {
Expand Down Expand Up @@ -95,11 +95,58 @@ class CSCompiler_Expr extends CSCompiler_Base {
})
}
case TBinop(op, e1, e2): {
result = binopToCS(op, e1, e2);
haxeExpr: expr,
def: CSExprStatement({
haxeExpr: expr,
def: CSBinop(
op,
csStatementToExpr(_compileExpression(e1)),
csStatementToExpr(_compileExpression(e2))
)
})
}
case TField(e, fa): {
result = fieldAccessToCS(e, fa);
case TField(e, fa):
{
haxeExpr: expr,
def: CSExprStatement({
haxeExpr: expr,
def: switch fa {
case FInstance(c, params, cf):
CSField(
csStatementToExpr(_compileExpression(e)),
CSFInstance(
compiler.typeComp.compileClassType(c.get()),
compiler.typeComp.compileTypeParams(params),
cf.get().name
)
);
case FStatic(c, cf):
CSField(
csStatementToExpr(_compileExpression(e)),
CSFStatic(
compiler.typeComp.compileClassType(c.get()),
// C# type inference should be able to infer generic types
// from arguments, but it also allows the types to be explicit.
// We might need that in some situation where inference is not enough?
[],
cf.get().name
)
);
case FAnon(cf):
// We rely on dynamic access to read anon fields, because for now,
// they will be backed with `haxe.lang.DynamicObject` anyway
compileDynamicGetField(expr, cf.get().name);
case FDynamic(s):
compileDynamicGetField(expr, s);
case FClosure(c, cf):
CSConst(CSNull); // TODO
case FEnum(e, ef):
CSConst(CSNull); // TODO
}
})
//result = fieldAccessToCS(e, fa);
}
/*
case TTypeExpr(m): {
result = compiler.compileModuleType(m);
}
Expand Down Expand Up @@ -307,13 +354,35 @@ class CSCompiler_Expr extends CSCompiler_Base {
}

/**
Generate an expression given a `Binop` and two typed expressions (from `TypedExprDef.TBinop`).
Generate a dynamic "getField" access
**/
function binopToCS(op: Binop, e1: TypedExpr, e2: TypedExpr): String {
var csExpr1 = _compileExpression(e1);
var csExpr2 = _compileExpression(e2);
final operatorStr = OperatorHelper.binopToString(op);
return csExpr1 + " " + operatorStr + " " + csExpr2;
function compileDynamicGetField(expr: TypedExpr, name: String): CSExprDef {
return CSCall(
{
haxeExpr: expr,
def: CSField(
{
haxeExpr: expr,
def: CSClassExpr("haxe.lang.Runtime")
},
CSFStatic(
"haxe.lang.Runtime",
[],
"getField"
)
)
},
[],
[
{
haxeExpr: expr,
def: CSConst(CSString(name))
}
// TODO
// add an integer argument used to retrieve fields names
// that are known at compile time in a faster way
]
);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/cscompiler/components/CSCompiler_Type.hx
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,13 @@ class CSCompiler_Type extends CSCompiler_Base {

}

function compileClassType(classType:ClassType):CSTypePath {
public function compileClassType(classType:ClassType):CSTypePath {

return compileClassName(classType, true);

}

function compileTypeParams(params:Array<Type>):Array<CSType> {
public function compileTypeParams(params:Array<Type>):Array<CSType> {

// TODO
return [];
Expand Down

0 comments on commit d54b8d9

Please sign in to comment.