View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2001-2004 Open World Ltd
4   // Copyright (C) 2005 Kevin Rogers
5   //
6   // This file is part of MillScript.
7   //
8   // MillScript is free software; you can redistribute it and/or modify it under
9   // the terms of the GNU General Public License as published by the Free
10  // Software Foundation; either version 2 of the License, or (at your option)
11  // any later version.
12  //
13  // MillScript is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  // more details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA  02111-1307  USA
21  ////////////////////////////////////////////////////////////////////////////////
22  package org.millscript.millscript.expr;
23  
24  import org.millscript.millscript.action.Action;
25  import org.millscript.millscript.action.VarAction;
26  import org.millscript.millscript.action.VarAlienAction;
27  import org.millscript.millscript.action.VarGlobalAction;
28  import org.millscript.millscript.action.VarLocalAction;
29  import org.millscript.millscript.alert.Alerts;
30  import org.millscript.millscript.vm.CompilerState;
31  
32  import java.util.Stack;
33  
34  /**
35   * This class implements a variable declaration expression. This can declare
36   * new variables and constants.
37   *
38   * @see org.millscript.millscript.syntax.VarSyntax
39   * @see VarAlienAction
40   * @see VarGlobalAction
41   * @see VarLocalAction
42   */
43  public final class VarExpr extends Expr< VarAction > {
44  
45      /**
46       * Boolean flag indicating if this new variable is a constant or not.
47       */
48      private final boolean isConst;
49  
50      /**
51       * The new variable name expression.
52       */
53      private final NameExpr name;
54  
55      /**
56       * The new variables value expression.
57       */
58      private final Expr< ? > value;
59  
60      /**
61       * Creates a new variable expression, to declare a variable/constant, with
62       * the specified name and value. The value expression must return a single
63       * result.
64       *
65       * @param   isconst <code>true</code> if this expression declares a new
66       *                  constant, <code>false</code> otherwise.
67       * @param   a       the name expression for the declared variable
68       * @param   b       the value expression for the declared variable
69       */
70      public VarExpr( final boolean isconst, final NameExpr a, final Expr< ? > b ) {
71          isConst = isconst;
72          name = a;
73          value = CheckExpr.make( b );
74      }
75  
76      /**
77       * @see org.millscript.millscript.expr.Expr#compileIt()
78       */
79      @Override
80      public VarAction compileIt() {
81          Action v = value.compile();
82          Ident id = name.getIdent();
83          if ( id instanceof GlobalIdent ) {
84              return new VarGlobalAction( id, v );
85          } else if ( id instanceof LocalIdent ) {
86              if ( id.isAlien() ) {
87                  return new VarAlienAction( id, v );
88              } else {
89                  return new VarLocalAction( id, v );
90              }
91          } else {
92              throw(
93                  Alerts.fault( "Unknown type of ident" ).mishap()
94              );
95          }
96      }
97  
98      /**
99       * Returns the declared variables name expression.
100      *
101      * @return  a {@link NameExpr} for the declared variables name.
102      */
103     NameExpr getVar() {
104         return name;
105     }
106 
107     /**
108      * @see org.millscript.millscript.expr.Expr#resolve(org.millscript.millscript.vm.CompilerState)
109      */
110     @Override
111     public void resolve( final CompilerState state ) {
112         // Check if the variable is already delcared and protected
113         // NOTE - This is used to protect MillScripts built-in variables against
114         //        accidental assignment
115         if ( state.getIsProtected( name.getName() ) ) {
116             throw(
117                 Alerts.compile(
118                     "Trying to redeclare a protected variable",
119                     "Most built-ins are protected against accidental assignment"
120                 ).culprit( "name", name.getName() ).mishap()
121             );
122         }
123         // Get the current scope
124         Stack< Expr > scopes = state.getScopes();
125         // Check if there are any scopes
126         if ( scopes.size() == 0 ) {
127             // No scopes, so this must be delcaring a global variable
128             name.declareGlobal( state, isConst );
129         } else {
130             // There are scopes, so we are declaring a local variable.
131             // Check if the current scope is a block
132             if ( scopes.peek() instanceof Block ) {
133                 // The current scope is a block, we are declaring a variable in
134                 // that block, hence it is used.
135                 Block b = (Block)scopes.peek();
136                 b.setIsUsed();
137             }
138             scopes.push( name );
139             name.declareLocal( isConst );
140         }
141         this.value.resolve( state );
142     }
143 
144     /**
145      * @see org.millscript.millscript.expr.Expr#showComponents(int)
146      */
147     @Override
148     void showComponents( final int n ) {
149         this.name.show( n );
150         this.value.show( n );
151     }
152 
153 }