use of kalang.ast.MethodNode in project kalang by kasonyang.
the class SemanticAnalyzer method validateAnnotation.
protected boolean validateAnnotation(AnnotationNode annotation) {
MethodNode[] mds = annotation.getAnnotationType().getDeclaredMethodNodes();
Set<String> attrKeys = annotation.values.keySet();
List<String> missingValues = new LinkedList<>();
for (MethodNode m : mds) {
String name = m.getName();
if (!attrKeys.contains(name)) {
missingValues.add(name);
}
}
if (missingValues.size() > 0) {
// TODO add offset on annotationNode
diagnosisReporter.report(Diagnosis.Kind.ERROR, "Missing attribute for annotation:" + missingValues.toString(), OffsetRange.NONE);
return false;
}
return true;
}
use of kalang.ast.MethodNode in project kalang by kasonyang.
the class ClassNodeMetaBuilder method visitMethodDecl.
@Override
public Object visitMethodDecl(KalangParser.MethodDeclContext ctx) {
String name;
Type type;
boolean isOverriding = ctx.OVERRIDE() != null;
if (ctx.prefix != null && ctx.prefix.getText().equals("constructor")) {
type = Types.VOID_TYPE;
name = "<init>";
} else {
if (ctx.type() == null) {
type = Types.VOID_TYPE;
} else {
type = astBuilder.parseType(ctx.returnType);
}
name = ctx.name.getText();
}
List<KalangParser.TypeContext> paramTypesCtx = ctx.paramTypes;
int modifier = astBuilder.parseModifier(ctx.varModifier());
Type[] paramTypes;
String[] paramNames;
if (paramTypesCtx != null) {
int paramSize = paramTypesCtx.size();
paramTypes = new Type[paramSize];
paramNames = new String[paramSize];
for (int i = 0; i < paramSize; i++) {
KalangParser.TypeContext t = paramTypesCtx.get(i);
paramTypes[i] = astBuilder.parseType(t);
paramNames[i] = ctx.paramIds.get(i).getText();
}
} else {
paramTypes = new Type[0];
paramNames = new String[0];
}
// check method duplicated before generate java stub
String mStr = MethodUtil.getDeclarationKey(name, paramTypes);
boolean existed = Arrays.asList(thisClazz.getDeclaredMethodNodes()).stream().anyMatch((m) -> {
return MethodUtil.getDeclarationKey(m).equals(mStr);
});
if (existed) {
// TODO should remove the duplicated method
diagnosisReporter.report(Diagnosis.Kind.ERROR, "declare method duplicately:" + mStr, ctx);
return null;
}
KalangParser.BlockStmtContext blockStmt = ctx.blockStmt();
if (blockStmt == null) {
if (ModifierUtil.isInterface(thisClazz.modifier)) {
modifier |= Modifier.ABSTRACT;
} else if (!Modifier.isAbstract(modifier)) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "method body required", ctx);
} else if (!Modifier.isAbstract(thisClazz.modifier)) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "declare abstract method in non-abstract class", ctx);
}
}
method = thisClazz.createMethodNode(type, name, modifier);
for (int i = 0; i < paramTypes.length; i++) {
method.createParameter(paramTypes[i], paramNames[i]);
}
for (AnnotationNode a : astBuilder.getAnnotations(ctx.annotation())) method.addAnnotation(a);
ObjectType superType = thisClazz.getSuperType();
if (superType == null) {
// the superType of interface may be null
superType = Types.getRootType();
}
MethodDescriptor overriddenMd = ClassTypeUtil.getMethodDescriptor(superType, mStr, thisClazz, true, true);
if (overriddenMd == null) {
overriddenMd = ClassTypeUtil.getMethodDescriptor(thisClazz.getInterfaces(), mStr, thisClazz, true, true);
}
if (isOverriding && overriddenMd == null) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "method does not override or implement a method from a supertype", ctx);
}
if (!isOverriding && overriddenMd != null) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "method overrides or implements a method from a supertype", ctx);
}
this.methodContexts.put(method, ctx);
KalangParser.BlockStmtContext bstm = ctx.blockStmt();
if (bstm != null) {
List<KalangParser.StatContext> stats = bstm.stat();
if (stats != null)
this.methodStatsContexts.put(method, stats.toArray(new KalangParser.StatContext[stats.size()]));
}
if (ctx.exceptionTypes != null) {
for (Token et : ctx.exceptionTypes) {
ObjectType exType = astBuilder.requireClassType(et);
if (exType != null) {
method.addExceptionType(exType);
}
}
}
astBuilder.mapAst(method, ctx);
MethodNode m = method;
method = null;
return m;
}
use of kalang.ast.MethodNode in project kalang by kasonyang.
the class ClassNodeMetaBuilder method visitScriptDef.
@Override
public Object visitScriptDef(KalangParser.ScriptDefContext ctx) {
// FIXME fix filename
// thisClazz.fileName = this.compilationUnit.getSource().getFileName();
thisClazz.setSuperType(this.getScriptType());
List<MethodDeclContext> mds = ctx.methodDecl();
if (mds != null) {
for (MethodDeclContext m : mds) {
visit(m);
}
}
MethodNode mm = thisClazz.createMethodNode(Types.VOID_TYPE, "execute", Modifier.PUBLIC);
mm.addExceptionType(Types.getExceptionClassType());
method = mm;
List<KalangParser.StatContext> stats = ctx.stat();
if (stats != null) {
this.methodStatsContexts.put(mm, stats.toArray(new KalangParser.StatContext[stats.size()]));
}
AstUtil.createEmptyConstructor(thisClazz);
AstUtil.createScriptMainMethodIfNotExists(thisClazz);
return null;
}
use of kalang.ast.MethodNode in project kalang by kasonyang.
the class AstUtil method createGetter.
public static void createGetter(ClassNode clazz, FieldDescriptor field, int accessModifier) {
String fn = field.getName();
String getterName = "get" + NameUtil.firstCharToUpperCase(fn);
boolean isStatic = isStatic(field.getModifier());
if (isStatic) {
accessModifier |= Modifier.STATIC;
}
MethodNode getter = clazz.createMethodNode(field.getType(), getterName, accessModifier);
// getter.offset = field.offset;
BlockStmt body = getter.getBody();
FieldExpr fe;
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 ReturnStmt(fe));
}
use of kalang.ast.MethodNode in project kalang by kasonyang.
the class AstUtil method createScriptMainMethodIfNotExists.
public static void createScriptMainMethodIfNotExists(ClassNode clazz) {
ClassType clazzType = Types.getClassType(clazz);
MethodDescriptor[] methods = clazzType.getMethodDescriptors(null, false, false);
Type[] argTypes = new Type[] { Types.getArrayType(Types.getStringClassType()) };
MethodDescriptor mainMethod = MethodUtil.getMethodDescriptor(methods, "main", argTypes);
if (mainMethod == null) {
MethodNode m = clazz.createMethodNode(Types.VOID_TYPE, "main", Modifier.PUBLIC + Modifier.STATIC);
ParameterNode p = m.createParameter(argTypes[0], "arg");
BlockStmt body = m.getBody();
try {
NewObjectExpr newScriptExpr = new NewObjectExpr(clazzType);
ObjectInvokeExpr invokeExpr = ObjectInvokeExpr.create(newScriptExpr, "run", new ExprNode[] { new ParameterExpr(p) });
body.statements.add(new ExprStmt(invokeExpr));
} catch (MethodNotFoundException | AmbiguousMethodException ex) {
throw Exceptions.unexceptedException(ex);
}
}
}
Aggregations