Search in sources :

Example 1 with ClassNode

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;
}
Also used : ClassNode(kalang.ast.ClassNode) Nullable(javax.annotation.Nullable)

Example 2 with ClassNode

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);
    }
}
Also used : ClassNode(kalang.ast.ClassNode) ConstExpr(kalang.ast.ConstExpr) LoopStmt(kalang.ast.LoopStmt) Statement(kalang.ast.Statement) BlockStmt(kalang.ast.BlockStmt) ArrayLengthExpr(kalang.ast.ArrayLengthExpr) LinkedList(java.util.LinkedList) AssignExpr(kalang.ast.AssignExpr) ExprNode(kalang.ast.ExprNode) ArrayType(kalang.core.ArrayType) MultiStmtExpr(kalang.ast.MultiStmtExpr) WildcardType(kalang.core.WildcardType) ArrayType(kalang.core.ArrayType) ClassType(kalang.core.ClassType) PrimitiveType(kalang.core.PrimitiveType) Type(kalang.core.Type) GenericType(kalang.core.GenericType) ObjectType(kalang.core.ObjectType) ExprStmt(kalang.ast.ExprStmt) CompareExpr(kalang.ast.CompareExpr) NewArrayExpr(kalang.ast.NewArrayExpr) VarDeclStmt(kalang.ast.VarDeclStmt) VarExpr(kalang.ast.VarExpr) VarObject(kalang.ast.VarObject) ClassReference(kalang.ast.ClassReference) LocalVarNode(kalang.ast.LocalVarNode) MathExpr(kalang.ast.MathExpr) ElementExpr(kalang.ast.ElementExpr)

Example 3 with ClassNode

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;
}
Also used : ClassNode(kalang.ast.ClassNode) Nullable(javax.annotation.Nullable)

Example 4 with ClassNode

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);
    }
}
Also used : ClassNode(kalang.ast.ClassNode) Statement(kalang.ast.Statement) BlockStmt(kalang.ast.BlockStmt) IfStatContext(kalang.antlr.KalangParser.IfStatContext) ContinueStatContext(kalang.antlr.KalangParser.ContinueStatContext) ExprStatContext(kalang.antlr.KalangParser.ExprStatContext) WhileStatContext(kalang.antlr.KalangParser.WhileStatContext) BreakStatContext(kalang.antlr.KalangParser.BreakStatContext) StatContext(kalang.antlr.KalangParser.StatContext) TryStatContext(kalang.antlr.KalangParser.TryStatContext) ForStatContext(kalang.antlr.KalangParser.ForStatContext) ReturnStatContext(kalang.antlr.KalangParser.ReturnStatContext) VarDeclStatContext(kalang.antlr.KalangParser.VarDeclStatContext) DoWhileStatContext(kalang.antlr.KalangParser.DoWhileStatContext) MethodNode(kalang.ast.MethodNode) MethodNotFoundException(kalang.MethodNotFoundException) AmbiguousMethodException(kalang.AmbiguousMethodException)

Example 5 with ClassNode

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;
}
Also used : ClassNode(kalang.ast.ClassNode) Token(org.antlr.v4.runtime.Token)

Aggregations

ClassNode (kalang.ast.ClassNode)21 ObjectType (kalang.core.ObjectType)8 Nullable (javax.annotation.Nullable)4 ClassType (kalang.core.ClassType)4 Token (org.antlr.v4.runtime.Token)4 BlockStmt (kalang.ast.BlockStmt)3 ArrayType (kalang.core.ArrayType)3 GenericType (kalang.core.GenericType)3 Type (kalang.core.Type)3 LinkedList (java.util.LinkedList)2 Nonnull (javax.annotation.Nonnull)2 AssignExpr (kalang.ast.AssignExpr)2 ConstExpr (kalang.ast.ConstExpr)2 ExprNode (kalang.ast.ExprNode)2 ExprStmt (kalang.ast.ExprStmt)2 MethodNode (kalang.ast.MethodNode)2 Statement (kalang.ast.Statement)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 AmbiguousMethodException (kalang.AmbiguousMethodException)1