use of kalang.ast.BlockStmt 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.BlockStmt in project kalang by kasonyang.
the class ClassNodeMetaBuilder method visitClassDef.
@Override
public Object visitClassDef(KalangParser.ClassDefContext ctx) {
thisClazz.annotations.addAll(astBuilder.getAnnotations(ctx.annotation()));
thisClazz.modifier = astBuilder.parseModifier(ctx.varModifier());
List<Token> gnrTypes = ctx.genericTypes;
if (gnrTypes != null && !gnrTypes.isEmpty()) {
for (Token g : gnrTypes) {
// TODO suport generic type bounds in syntax
GenericType gt = new GenericType(g.getText(), Types.getRootType(), null, NullableKind.NONNULL);
thisClazz.declareGenericType(gt);
}
}
ObjectType superType = null;
if (ctx.parentClass != null) {
ObjectType parentClass = astBuilder.parseClassType(ctx.parentClass);
if (parentClass != null) {
superType = parentClass;
}
} else {
superType = Types.getRootType();
}
if (Modifier.isInterface(thisClazz.modifier)) {
// TODO update syntax to support:interface extends T1,T2...
thisClazz.addInterface(superType);
} else {
thisClazz.setSuperType(superType);
}
if (ctx.interfaces != null && ctx.interfaces.size() > 0) {
for (KalangParser.ClassTypeContext itf : ctx.interfaces) {
ObjectType itfClz = astBuilder.parseClassType(itf);
if (itfClz != null) {
thisClazz.addInterface(itfClz);
}
}
}
if (this.isDeclaringNonStaticInnerClass()) {
ClassNode parentClass = thisClazz.enclosingClass;
if (parentClass == null) {
throw Exceptions.unexceptedValue(parentClass);
}
thisClazz.createField(Types.getClassType(parentClass), "this$0", Modifier.PRIVATE | ModifierConstant.SYNTHETIC);
}
visit(ctx.classBody());
if (!ModifierUtil.isInterface(thisClazz.modifier) && !AstUtil.containsConstructor(thisClazz) && !AstUtil.createEmptyConstructor(thisClazz)) {
this.diagnosisReporter.report(Diagnosis.Kind.ERROR, "failed to create constructor with no parameters", ctx);
}
MethodNode[] methods = thisClazz.getDeclaredMethodNodes();
for (int i = 0; i < methods.length; i++) {
MethodNode node = methods[i];
BlockStmt body = node.getBody();
if (body != null) {
if (AstUtil.isConstructor(node)) {
// constructor
if (this.isDeclaringNonStaticInnerClass()) {
ClassNode enclosingClass = thisClazz.enclosingClass;
if (enclosingClass == null) {
throw Exceptions.unexceptedValue(enclosingClass);
}
ParameterNode outerInstanceParam = node.createParameter(0, Types.getClassType(enclosingClass), "this$0");
ExprNode parentFieldExpr = astBuilder.getObjectFieldExpr(new ThisExpr(Types.getClassType(thisClazz)), "this$0", ParserRuleContext.EMPTY);
if (parentFieldExpr == null) {
throw Exceptions.unexceptedValue(parentFieldExpr);
}
body.statements.add(1, new ExprStmt(new AssignExpr((AssignableExpr) parentFieldExpr, new ParameterExpr(outerInstanceParam))));
}
}
}
}
for (FieldNode fieldNode : thisClazz.getFields()) {
int mdf = fieldNode.modifier;
if (!AstUtil.hasGetter(thisClazz, fieldNode)) {
AstUtil.createGetter(thisClazz, fieldNode, mdf);
}
if (!AstUtil.hasSetter(thisClazz, fieldNode)) {
AstUtil.createSetter(thisClazz, fieldNode, mdf);
}
fieldNode.modifier = ModifierUtil.setPrivate(mdf);
}
return null;
}
use of kalang.ast.BlockStmt in project kalang by kasonyang.
the class AstUtil method createSetter.
public static void createSetter(ClassNode clazz, FieldDescriptor field, int accessModifier) {
String fn = field.getName();
String setterName = "set" + NameUtil.firstCharToUpperCase(fn);
boolean isStatic = isStatic(field.getModifier());
if (isStatic) {
accessModifier |= Modifier.STATIC;
}
MethodNode setter = clazz.createMethodNode(Types.VOID_TYPE, setterName, accessModifier);
// setter.offset = field.offset;
ParameterNode param = setter.createParameter(field.getType(), field.getName());
BlockStmt body = setter.getBody();
FieldExpr fe;
ExprNode paramVal = new ParameterExpr(param);
ClassReference cr = new ClassReference(clazz);
if (isStatic) {
fe = new StaticFieldExpr(cr, field);
} else {
fe = new ObjectFieldExpr(new ThisExpr(Types.getClassType(clazz)), field);
}
body.statements.add(new ExprStmt(new AssignExpr(fe, paramVal)));
}
use of kalang.ast.BlockStmt in project kalang by kasonyang.
the class AstUtil method createEmptyConstructor.
public static boolean createEmptyConstructor(ClassNode clazzNode) {
ObjectType supType = clazzNode.getSuperType();
if (supType == null) {
throw new RuntimeException("super type is null:" + clazzNode.name);
}
ConstructorDescriptor[] constructors = supType.getConstructorDescriptors(clazzNode);
ConstructorDescriptor m = MethodUtil.getConstructorDescriptor(constructors, null);
if (m != null) {
MethodNode mm = clazzNode.createMethodNode(Types.VOID_TYPE, m.getName(), m.getModifier());
for (Type e : m.getExceptionTypes()) mm.addExceptionType(e);
ParameterDescriptor[] pds = m.getParameterDescriptors();
for (ParameterDescriptor pd : pds) {
ParameterNode p = mm.createParameter(pd.getType(), pd.getName());
// TODO update mm.createParameter
p.modifier = pd.getModifier();
}
BlockStmt body = mm.getBody();
ParameterNode[] parameters = mm.getParameters();
ExprNode[] params = new ExprNode[parameters.length];
for (int i = 0; i < params.length; i++) {
params[i] = new ParameterExpr(parameters[i]);
}
body.statements.add(new ExprStmt(new ObjectInvokeExpr(new SuperExpr(clazzNode), m, params)));
return true;
} else {
return false;
}
}
use of kalang.ast.BlockStmt in project kalang by kasonyang.
the class AstBuilder method visitForEachStat.
@Override
public Object visitForEachStat(KalangParser.ForEachStatContext ctx) {
BlockStmt block = newBlock();
ExprNode expr = this.visitExpression(ctx.expression());
Type exprType = expr.getType();
List<TerminalNode> idsCtx = ctx.Identifier();
VarExpr indexVarExpr = null;
TerminalNode varId;
if (idsCtx.size() == 1) {
varId = idsCtx.get(0);
} else {
TerminalNode indexId = idsCtx.get(0);
LocalVarNode indexVar = this.declareLocalVar(indexId.getText(), Types.INT_TYPE, Modifier.FINAL, ctx);
if (indexVar == null)
return null;
block.statements.add(new VarDeclStmt(indexVar));
indexVarExpr = new VarExpr(indexVar);
varId = idsCtx.get(1);
}
LoopStmt loopStmt;
if (exprType instanceof ArrayType) {
LocalVarNode localVarNode = this.declareLocalVar(varId.getText(), ((ArrayType) exprType).getComponentType(), Modifier.FINAL, ctx);
if (localVarNode == null)
return null;
VarExpr localVariable = new VarExpr(localVarNode);
block.statements.add(new VarDeclStmt(localVarNode));
LocalVarNode lenVar = this.declareTempLocalVar(Types.INT_TYPE);
LocalVarNode counterVar = this.declareTempLocalVar(Types.INT_TYPE);
// var len
block.statements.add(new VarDeclStmt(lenVar));
// var i
block.statements.add(new VarDeclStmt(counterVar));
VarExpr counterVarExpr = new VarExpr(counterVar);
VarExpr lenVarExpr = new VarExpr(lenVar);
block.statements.add(new ExprStmt(new AssignExpr(lenVarExpr, new ArrayLengthExpr(expr))));
// l = array.length
block.statements.add(new ExprStmt(new AssignExpr(counterVarExpr, new ConstExpr(0))));
// i=0
ExprNode cnd = new CompareExpr(counterVarExpr, lenVarExpr, CompareExpr.OP_LT);
BlockStmt loopBody = this.newBlock();
loopBody.statements.add(new ExprStmt(new AssignExpr(localVariable, new ElementExpr(expr, counterVarExpr))));
if (indexVarExpr != null) {
loopBody.statements.add(new ExprStmt(new AssignExpr(indexVarExpr, counterVarExpr)));
}
loopBody.statements.add(visitStat(ctx.stat()));
popBlock();
BlockStmt updateBs = newBlock();
// increment counter
updateBs.statements.add(new ExprStmt(new AssignExpr(counterVarExpr, new MathExpr(counterVarExpr, new ConstExpr(1), MathExpr.OP_ADD))));
popBlock();
loopStmt = new LoopStmt(cnd, null, loopBody, updateBs);
} else {
ObjectType iterType = Types.getIterableClassType();
if (iterType.isAssignableFrom(exprType)) {
ObjectInvokeExpr getIterableExpr;
try {
getIterableExpr = ObjectInvokeExpr.create(expr, "iterator", null);
} catch (MethodNotFoundException | AmbiguousMethodException ex) {
throw Exceptions.unexceptedException(ex);
}
LocalVarNode iterableVarNode = this.declareTempLocalVar(getIterableExpr.getType());
block.statements.add(new VarDeclStmt(iterableVarNode));
VarExpr iterableVarExpr = new VarExpr(iterableVarNode);
block.statements.add(new ExprStmt(new AssignExpr(iterableVarExpr, getIterableExpr)));
// set index = 0
if (indexVarExpr != null) {
block.statements.add(new ExprStmt(new AssignExpr(indexVarExpr, new ConstExpr(0))));
}
ObjectInvokeExpr cnd;
try {
cnd = ObjectInvokeExpr.create(iterableVarExpr, "hasNext", null);
} catch (MethodNotFoundException | AmbiguousMethodException ex) {
throw Exceptions.unexceptedException(ex);
}
BlockStmt loopBody = this.newBlock();
ObjectInvokeExpr nextInvokeExpr;
try {
nextInvokeExpr = ObjectInvokeExpr.create(iterableVarExpr, "next", null);
} catch (MethodNotFoundException | AmbiguousMethodException ex) {
throw Exceptions.unexceptedException(ex);
}
LocalVarNode localVarNode = this.declareLocalVar(varId.getText(), nextInvokeExpr.getType(), Modifier.FINAL, ctx);
if (localVarNode == null)
return null;
VarExpr localVariable = new VarExpr(localVarNode);
loopBody.statements.add(new VarDeclStmt(localVarNode));
loopBody.statements.add(new ExprStmt(new AssignExpr(localVariable, new CastExpr(localVariable.getType(), nextInvokeExpr))));
loopBody.statements.add(visitStat(ctx.stat()));
popBlock();
BlockStmt updateBs = newBlock();
if (indexVarExpr != null) {
// do index++
updateBs.statements.add(new ExprStmt(new AssignExpr(indexVarExpr, new MathExpr(indexVarExpr, new ConstExpr(1), BinaryExpr.OP_ADD))));
}
popBlock();
loopStmt = new LoopStmt(cnd, null, loopBody, updateBs);
} else {
this.handleSyntaxError("require array type or iterable type", ctx.expression());
loopStmt = null;
}
}
popBlock();
if (loopStmt != null)
block.statements.add(loopStmt);
return block;
}
Aggregations