use of kalang.ast.ClassNode in project kalang by kasonyang.
the class AstBuilder method getAst.
@Nullable
private ClassNode getAst(String id) {
String resolvedName = this.typeNameResolver.resolve(id, topClass, thisClazz);
ClassNode ast = resolvedName == null ? null : astLoader.getAst(resolvedName);
return ast;
}
use of kalang.ast.ClassNode in project kalang by kasonyang.
the class AstBuilder method visitInvokeExpr.
@Override
public AstNode visitInvokeExpr(InvokeExprContext ctx) {
Object target = visit(ctx.target);
if (target == null)
return null;
String mdName = ctx.Identifier().getText();
String refKey = ctx.refKey.getText();
if (refKey.equals(".")) {
if (target instanceof ClassReference) {
return getStaticInvokeExpr((ClassReference) target, mdName, ctx.params, ctx);
} else if (target instanceof ExprNode) {
return getObjectInvokeExpr((ExprNode) target, mdName, ctx.params, ctx);
} else {
throw Exceptions.unexceptedValue(target);
}
} else if (refKey.equals("->")) {
ExprNode[] invokeArgs = new ExprNode[3];
ExprNode[] params = new ExprNode[ctx.params.size()];
if (target instanceof ClassReference) {
invokeArgs[0] = new ConstExpr(null);
} else if (target instanceof ExprNode) {
invokeArgs[0] = ((ExprNode) target);
}
invokeArgs[1] = new ConstExpr(mdName);
for (int i = 0; i < params.length; i++) {
params[i] = visitExpression(ctx.params.get(i));
}
invokeArgs[2] = createInitializedArray(Types.getRootType(), params);
ClassNode dispatcherAst = getAst("kalang.runtime.dynamic.MethodDispatcher");
if (dispatcherAst == null) {
throw Exceptions.unexceptedException("Runtime library is required!");
}
return getStaticInvokeExpr(new ClassReference(dispatcherAst), "invokeMethod", invokeArgs, ctx);
} else if (refKey.equals("*.")) {
if (!(target instanceof ExprNode)) {
handleSyntaxError("expression required", ctx.expression);
return null;
}
ExprNode targetExpr = (ExprNode) target;
Type targetType = targetExpr.getType();
if (!(targetType instanceof ArrayType)) {
handleSyntaxError("array required", ctx.expression);
return null;
}
List<Statement> stats = new LinkedList();
LocalVarNode varArrLen = this.declareTempLocalVar(Types.INT_TYPE);
LocalVarNode varCounter = this.declareTempLocalVar(Types.INT_TYPE);
stats.add(new VarDeclStmt(Arrays.asList(varArrLen, varCounter)));
VarExpr varArrLenExpr = new VarExpr(varArrLen);
VarExpr varCounterExpr = new VarExpr(varCounter);
stats.add(new ExprStmt(new AssignExpr(varArrLenExpr, new ArrayLengthExpr(targetExpr))));
stats.add(new ExprStmt(new AssignExpr(varCounterExpr, new ConstExpr(0))));
CompareExpr conditionExpr = new CompareExpr(varCounterExpr, varArrLenExpr, CompareExpr.OP_LT);
ExprNode targetEleExpr = new ElementExpr(targetExpr, varCounterExpr);
ExprNode invokeExpr = getObjectInvokeExpr(targetEleExpr, mdName, ctx.params, ctx);
if (invokeExpr == null)
return null;
LocalVarNode varRet = this.declareTempLocalVar(Types.getArrayType(invokeExpr.getType()));
VarExpr varRetExpr = new VarExpr(varRet);
stats.add(new VarDeclStmt(varRet));
stats.add(new ExprStmt(new AssignExpr(varRetExpr, new NewArrayExpr(invokeExpr.getType(), varArrLenExpr))));
BlockStmt loopBody = this.newBlock();
loopBody.statements.add(new ExprStmt(new AssignExpr(new ElementExpr(varRetExpr, varCounterExpr), invokeExpr)));
popBlock();
BlockStmt updateBs = newBlock();
updateBs.statements.add(new ExprStmt(new AssignExpr(varCounterExpr, new MathExpr(varCounterExpr, new ConstExpr(1), MathExpr.OP_ADD))));
this.popBlock();
LoopStmt loopStmt = new LoopStmt(conditionExpr, null, loopBody, updateBs);
stats.add(loopStmt);
return new MultiStmtExpr(stats, varRetExpr);
} else {
throw Exceptions.unexceptedException(refKey);
}
}
use of kalang.ast.ClassNode in project kalang by kasonyang.
the class AstBuilder method requireAst.
/**
* checks whether a class is available
* @param id
* @param token
* @return
*/
@Nullable
private ClassNode requireAst(String id, Token token) {
String resolvedName = this.typeNameResolver.resolve(id, topClass, thisClazz);
ClassNode ast = resolvedName == null ? null : astLoader.getAst(resolvedName);
if (ast == null) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "ast not found:" + id, token);
}
return ast;
}
use of kalang.ast.ClassNode in project kalang by kasonyang.
the class AstBuilder method visitMethods.
private void visitMethods(ClassNode clazz) {
thisClazz = clazz;
for (MethodNode m : thisClazz.getDeclaredMethodNodes()) {
BlockStmt mbody = m.getBody();
StatContext[] stats = classNodeMetaBuilder.getStatContexts(m);
if (stats != null) {
method = m;
returned = false;
visitBlockStmt(stats, mbody);
boolean needReturn = (m.getType() != null && !m.getType().equals(Types.VOID_TYPE));
if (m.getBody() != null && needReturn && !returned) {
this.diagnosisReporter.report(Diagnosis.Kind.ERROR, "Missing return statement in method:" + MethodUtil.toString(method), classNodeMetaBuilder.getMethodDeclContext(m));
}
new InitializationAnalyzer(compilationUnit, astLoader).check(clazz, m);
}
if (AstUtil.isConstructor(m)) {
@SuppressWarnings("null") List<Statement> bodyStmts = mbody.statements;
if (!AstUtil.hasConstructorCallStatement(bodyStmts)) {
try {
bodyStmts.add(0, AstUtil.createDefaultSuperConstructorCall(thisClazz));
} catch (MethodNotFoundException | AmbiguousMethodException ex) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "default constructor not found", classNodeMetaBuilder.getMethodDeclContext(m));
}
}
// check super()
int stmtsSize = mbody.statements.size();
assert stmtsSize > 0;
Statement firstStmt = mbody.statements.get(0);
if (!AstUtil.isConstructorCallStatement(firstStmt)) {
// TODO handle error
throw new RuntimeException("missing constructor call");
}
mbody.statements.addAll(1, this.thisClazz.initStmts);
}
}
for (ClassNode c : clazz.classes) {
this.visitMethods(c);
}
}
use of kalang.ast.ClassNode in project kalang by kasonyang.
the class ClassNodeBuilder method visitClassDef.
@Override
public Object visitClassDef(KalangParser.ClassDefContext ctx) {
ClassNode oldClass = thisClazz;
Token nameIdentifier = ctx.name;
int modifier = astBuilder.parseModifier(ctx.varModifier());
if (inScriptMode) {
modifier |= Modifier.STATIC;
}
Token classKind = ctx.classKind;
boolean isInterface = false;
if (classKind != null) {
if (classKind.getText().equals("interface")) {
modifier |= Modifier.ABSTRACT | Modifier.INTERFACE;
isInterface = true;
}
}
String classDefName;
if (oldClass != null) {
if (nameIdentifier == null) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "Identifier excepted", ctx);
return null;
}
classDefName = oldClass.name + "$" + nameIdentifier.getText();
} else {
classDefName = astBuilder.getClassName();
}
ClassNode theClass = thisClazz = new ClassNode(classDefName, modifier);
astBuilder.thisClazz = thisClazz;
this.defContext.put(theClass, ctx);
if (oldClass == null) {
this.topClass = theClass;
} else {
oldClass.classes.add(thisClazz);
thisClazz.enclosingClass = oldClass;
}
// FIXME fix file name
// thisClazz.fileName = this.compilationUnit.getSource().getFileName();
boolean oldScriptMode = this.inScriptMode;
this.inScriptMode = false;
visit(ctx.classBody());
this.inScriptMode = oldScriptMode;
astBuilder.mapAst(thisClazz, ctx);
thisClazz = oldClass;
return null;
}
Aggregations