Home-Produkte-Testarea-Kontakt-Datenschutz-Aktualisiert: 10-Jul-2009
< Voriger Tag   Nächster Tag >

Freitag, 10. Juli 2009

Lx0: Prototyp -- Zuweisung mit Typüberprüfung

Die Zuweisung enthält nun eine Typüberprüfung, der Quelltext zum Lx0-Prototyp ist dadurch deutlich erweitert worden.

Mit der Typüberprüfung gibt es bei folgenden Beispiel nun eine Fehlermeldung, da 512 vom Typ uword ist:

ubyte $count;

$count := 512;

LxNode

Um innerhalb des ASTs den Typ zu speichern, habe ich CommonTree erweitert. Damit haben zwar auch AST-Knoten die keinen Typ brauchen ein Typ-Attribut aber das dürfte die einfachste Möglichkeit sein, die Typinformation zu verwalten:

public class LxNode extends CommonTree {
    public Type type;


    public LxNode(Token t) {
         super(t);
    }
}

In Grammar.g und TreeWalker.g ist der ASTLabelType somit nun LxNode.

Zusätzlich muss noch der CommonTreeAdaptor erweitert werden, ansonsten gibt es bei der Ausführung ClassCastExceptions. Compiler.java:

public class Compiler {
    
    /**
     * Custom adaptor to create LxNode nodes
    */
    class LxNodeAdaptor extends CommonTreeAdaptor {
        public Object create(Token payload) {
            return new LxNode(payload);
        }


        public Object dupNode(Object t) {
            if(null == t) {
                return null;
            }

            return create(((LxNode)t).token);
        }
    }
    
    ...

            GrammarParser     parser = new GrammarParser(tokens);
            LxNodeAdaptor adaptor = new LxNodeAdaptor(); // Adaptor for custom node
            parser.setTreeAdaptor(adaptor);

            Tree ast = (Tree) parser.program().getTree();
            System.out.println(ast.toString());

   ...

public Object dupNode(Object t) muss nicht in allen Fällen überschrieben werden. Hier ginge es auch ohne aber wenn aus einen AST wieder ein AST generiert wird, ist es z.B. nötig und wenn man die Methode immer überschreibt, braucht man sich keine Gedanken darüber machen, ob's gerade nötig ist oder nicht.

Verwaltung der Typen

Die Typen werden mit den Klassen Type und Types verwaltet. Erstere ist ein einzelner Typ, zweite ist ähnlich wie Scope/SymbolTable aufgebaut zur Verwaltung verschiedener Typen:

public class Type {
   public  String name;
   private List<Type> compatible = new ArrayList();

    public void addCompatible(Type type) {}
    public boolean isCompatibleWith(Type type) {}
    public String maxType(Type type) {}
}

name ist der Name des Typs (ubyte, uword, ...). In der compatible-Liste stehen die kompatiblen Typen. Im Fall von ulong sind dies uword und ubyte. Diese Liste wird von isCompatibleWith zur Überprüfung auf Kompatibilität benutzt.

maxType() liefert von zwei Typen den größeren zurück: ubyte.maxType(ulong) ergibt "ulong" als Rückgabe.

Assign

Innerhalb des TreeWalkers steht der LxNode in $regelname.start. Für expr erhält man den Typ damit via Type exprType = $expr.start.type;:

assign
    : ^(ASSIGN VARNAME expr) 
      {if(!csc.exists($VARNAME.text)) {
           errors++;
           System.err.println("ERROR: " + $VARNAME.text + " not declared in line " + $ASSIGN.getLine());
       } else {
           Type varType = csc.getSymbol($VARNAME.text).type;
           Type exprType =  $expr.start.type;
           // TODO Runtimecheck
           if(!varType.isCompatibleWith(exprType)) {
               errors++;
               System.err.println("ERROR: " + varType.name + " " + $VARNAME.text + " not compatible with " + exprType.name + " in line " + $ASSIGN.getLine());
           }
       }
      }
    -> assign(id={csc.getIdent($VARNAME.text)},expr={$expr.st})
    ;

Typ von INTEGER

Zur Erkennung zu großer Integerzahlen sowie zur Bestimmung des Typs benutze ich BigInteger:

    | INTEGER 
      {BigInteger integer = new BigInteger($INTEGER.text);
       if(integer.compareTo(new BigInteger("4294967295")) == 1) {
           errors++;
           System.err.println("ERROR: Integer " + $INTEGER.text + " to big in line " + $INTEGER.token.getLine());
       } else if (integer.compareTo(new BigInteger("257")) == -1) {
           $start.type = types.getType("ubyte");
       } else if (integer.compareTo(new BigInteger("65536")) == -1) {
           $start.type = types.getType("uword");
       } else {
           $start.type = types.getType("ulong");
       }
      }

Die neu hinzugekommende Typüberprüfung ist zwar unvollständig und von der Implementierung her alles andere als schön aber ein wichtiger Schritt für die Fertigstellung des Prototyps. Fehlt allerdings immer noch die Typüberprüfung beim Aufruf von Prozeduren...

Quelltext

Der komplette Lx0-Quelltext steht in Subversion.

[Direktlink]

< Voriger Tag   Nächster Tag >

  RSS V0.91

<Juli 2009 >
  0102030405
06070809101112
13141516171819
20212223242526
2728293031  

Home-Produkte-Testarea-Kontakt-Datenschutz-Aktualisiert: 10-Jul-2009
(C) 2000-2018 by Sven Drieling