changeset 684:10b314bf37e3

Added module dil.semantic.Pass2.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Mon, 21 Jan 2008 18:40:55 +0100
parents 1ae72234db26
children c5fd3b7bfcab
files trunk/src/dil/ast/Expression.d trunk/src/dil/semantic/Analysis.d trunk/src/dil/semantic/Pass2.d trunk/src/main.d
diffstat 4 files changed, 282 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/dil/ast/Expression.d	Mon Jan 21 17:10:12 2008 +0100
+++ b/trunk/src/dil/ast/Expression.d	Mon Jan 21 18:40:55 2008 +0100
@@ -17,9 +17,4 @@
   {
     super(NodeCategory.Expression);
   }
-
-  Expression evaluate()
-  {
-    return null;
-  }
 }
--- a/trunk/src/dil/semantic/Analysis.d	Mon Jan 21 17:10:12 2008 +0100
+++ b/trunk/src/dil/semantic/Analysis.d	Mon Jan 21 18:40:55 2008 +0100
@@ -31,7 +31,7 @@
 
   foreach (arg; args)
   {
-    auto e = arg.evaluate();
+    auto e = arg/+.evaluate()+/;
     if (e is null)
     {
       // scop.error(e.begin, "expression is not evaluatable at compile time");
@@ -54,7 +54,7 @@
   if (args.length != 1)
     return /*scop.error(pragmaLoc, "expected one expression argument to pragma")*/;
 
-  auto e = args[0].evaluate();
+  auto e = args[0]/+.evaluate()+/;
   if (e is null)
   {
     // scop.error(e.begin, "expression is not evaluatable at compile time");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/semantic/Pass2.d	Mon Jan 21 18:40:55 2008 +0100
@@ -0,0 +1,278 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module dil.semantic.Pass2;
+
+import dil.ast.DefaultVisitor;
+import dil.ast.Node,
+       dil.ast.Declarations,
+       dil.ast.Expressions,
+       dil.ast.Statements,
+       dil.ast.Types,
+       dil.ast.Parameters;
+import dil.lexer.Identifier;
+import dil.semantic.Symbol,
+       dil.semantic.Symbols,
+       dil.semantic.Types,
+       dil.semantic.Scope,
+       dil.semantic.Module,
+       dil.semantic.Analysis;
+import dil.parser.Parser;
+import dil.Location;
+import dil.Information;
+import dil.Messages;
+import dil.Enums;
+import dil.CompilerInfo;
+import common;
+
+class SemanticPass2 : DefaultVisitor
+{
+  Scope scop; /// The current scope.
+  Module modul; /// The module to be semantically checked.
+
+  this(Module modul)
+  {
+    this.modul = modul;
+  }
+
+  /// Start semantic analysis.
+  void start()
+  {
+    assert(modul.root !is null);
+    // Create module scope.
+    scop = new Scope();
+    scop.symbol = modul; // Set this module as the scope's symbol.
+    scop.infoMan = modul.infoMan;
+    visit(modul.root);
+  }
+
+  void enterScope(ScopeSymbol s)
+  {
+    scop = scop.enter(s);
+  }
+
+  void exitScope()
+  {
+    scop = scop.exit();
+  }
+
+  void error(Token* token, char[] formatMsg, ...)
+  {
+    auto location = token.getErrorLocation();
+    auto msg = Format(_arguments, _argptr, formatMsg);
+    modul.infoMan ~= new SemanticError(location, msg);
+  }
+
+  private alias Declaration D;
+  private alias Expression E;
+  private alias Statement S;
+  private alias TypeNode T;
+
+override
+{
+  D visit(CompoundDeclaration d)
+  {
+    return super.visit(d);
+  }
+
+  D visit(MixinDeclaration md)
+  {
+    /+
+    if (type)
+      return this.expr;
+    // TODO:
+    auto expr = this.expr.semantic(scop);
+    expr = expr.evaluate();
+    if (expr is null)
+      return this;
+    auto strExpr = TryCast!(StringExpression)(expr);
+    if (strExpr is null)
+     error(scop, MSG.MixinArgumentMustBeString);
+    else
+    {
+      auto loc = this.begin.getErrorLocation();
+      auto filePath = loc.filePath;
+      auto parser = new_ExpressionParser(strExpr.getString(), filePath, scop.infoMan);
+      expr = parser.parse();
+      expr = expr.semantic(scop);
+    }
+    this.expr = expr;
+    this.type = expr.type;
+    return expr;
+    +/
+    return md;
+  }
+
+  T visit(PointerType t)
+  {
+    t.type = visitT(t.next).type.ptrTo();
+    return t;
+  }
+
+  T visit(IntegralType t)
+  {
+    // A table mapping the kind of a token to its corresponding semantic Type.
+    TypeBasic[TOK] tok2Type = [
+      TOK.Char : Types.Char,   TOK.Wchar : Types.Wchar,   TOK.Dchar : Types.Dchar, TOK.Bool : Types.Bool,
+      TOK.Byte : Types.Byte,   TOK.Ubyte : Types.Ubyte,   TOK.Short : Types.Short, TOK.Ushort : Types.Ushort,
+      TOK.Int : Types.Int,    TOK.Uint : Types.Uint,    TOK.Long : Types.Long,  TOK.Ulong : Types.Ulong,
+      TOK.Cent : Types.Cent,   TOK.Ucent : Types.Ucent,
+      TOK.Float : Types.Float,  TOK.Double : Types.Double,  TOK.Real : Types.Real,
+      TOK.Ifloat : Types.Ifloat, TOK.Idouble : Types.Idouble, TOK.Ireal : Types.Ireal,
+      TOK.Cfloat : Types.Cfloat, TOK.Cdouble : Types.Cdouble, TOK.Creal : Types.Creal, TOK.Void : Types.Void
+    ];
+    t.type = tok2Type[t.tok];
+    return t;
+  }
+
+  E visit(ParenExpression e)
+  {
+    if (!e.type)
+    {
+      e.next = visitE(e.next);
+      e.type = e.next.type;
+    }
+    return e;
+  }
+
+  E visit(CommaExpression e)
+  {
+    if (!e.type)
+    {
+      e.left = visitE(e.left);
+      e.right = visitE(e.right);
+      e.type = e.right.type;
+    }
+    return e;
+  }
+
+  E visit(OrOrExpression)
+  { return null; }
+
+  E visit(AndAndExpression)
+  { return null; }
+
+  E visit(SpecialTokenExpression e)
+  {
+    if (e.type)
+      return e.value;
+    switch (e.specialToken.kind)
+    {
+    case TOK.LINE, TOK.VERSION:
+      e.value = new IntExpression(e.specialToken.uint_, Types.Uint);
+      break;
+    case TOK.FILE, TOK.DATE, TOK.TIME, TOK.TIMESTAMP, TOK.VENDOR:
+      e.value = new StringExpression(e.specialToken.str);
+      break;
+    default:
+      assert(0);
+    }
+    e.type = e.value.type;
+    return e.value;
+  }
+
+  E visit(DollarExpression e)
+  {
+    if (e.type)
+      return e;
+    e.type = Types.Size_t;
+    // if (!inArraySubscript)
+    //   error("$ can only be in an array subscript.");
+    return e;
+  }
+
+  E visit(NullExpression e)
+  {
+    if (!e.type)
+      e.type = Types.Void_ptr;
+    return e;
+  }
+
+  E visit(BoolExpression e)
+  {
+    if (e.type)
+      return e;
+    e.value = new IntExpression(e.toBool(), Types.Bool);
+    e.type = Types.Bool;
+    return e;
+  }
+
+  E visit(IntExpression e)
+  {
+    if (e.type)
+      return e;
+
+    if (e.number & 0x8000_0000_0000_0000)
+      e.type = Types.Ulong; // 0xFFFF_FFFF_FFFF_FFFF
+    else if (e.number & 0xFFFF_FFFF_0000_0000)
+      e.type = Types.Long; // 0x7FFF_FFFF_FFFF_FFFF
+    else if (e.number & 0x8000_0000)
+      e.type = Types.Uint; // 0xFFFF_FFFF
+    else
+      e.type = Types.Int; // 0x7FFF_FFFF
+    return e;
+  }
+
+  E visit(RealExpression e)
+  {
+    if (e.type)
+      e.type = Types.Double;
+    return e;
+  }
+
+  E visit(ComplexExpression e)
+  {
+    if (!e.type)
+      e.type = Types.Cdouble;
+    return e;
+  }
+
+  E visit(CharExpression e)
+  {
+    if (e.type)
+      return e;
+    if (e.character <= 0xFF)
+      e.type = Types.Char;
+    else if (e.character <= 0xFFFF)
+      e.type = Types.Wchar;
+    else
+      e.type = Types.Dchar;
+    return e;
+  }
+
+  E visit(StringExpression e)
+  {
+    return e;
+  }
+
+  E visit(MixinExpression me)
+  {
+    if (me.type)
+      return me.expr;
+    auto expr = visitE(me.expr);
+    // TODO: expr = expr.evaluate();
+    if (expr is null)
+      return me;
+    auto stringExpr = expr.Is!(StringExpression);
+    if (stringExpr is null)
+     error(me.begin, MSG.MixinArgumentMustBeString);
+    else
+    {
+      auto loc = me.begin.getErrorLocation();
+      auto filePath = loc.filePath;
+      auto parser = new Parser(stringExpr.getString(), filePath, scop.infoMan);
+      expr = parser.start2();
+      expr = visitE(expr); // Check expression.
+    }
+    me.expr = expr;
+    me.type = expr.type;
+    return me.expr;
+  }
+
+  E visit(ImportExpression e)
+  {
+    return e;
+  }
+}
+}
\ No newline at end of file
--- a/trunk/src/main.d	Mon Jan 21 17:10:12 2008 +0100
+++ b/trunk/src/main.d	Mon Jan 21 18:40:55 2008 +0100
@@ -14,7 +14,8 @@
        dil.ast.Visitor;
 import dil.semantic.Module;
 import dil.semantic.Symbols;
-import dil.semantic.Pass1;
+import dil.semantic.Pass1,
+       dil.semantic.Pass2;
 import dil.translator.German;
 import dil.doc.Doc;
 import dil.Messages;