some refactoring to delay typing variables until they are used. this is in anticipati...
authorMichael Welch <michaelgwelch@gmail.com>
Wed, 17 Jan 2007 04:50:27 +0000 (04:50 +0000)
committerMichael Welch <michaelgwelch@gmail.com>
Wed, 17 Jan 2007 04:50:27 +0000 (04:50 +0000)
mbasic/Lexer.cs
mbasic/Parser.cs
mbasic/Program.cs
mbasic/SymbolTable.cs
mbasic/SyntaxTree/Assign.cs
mbasic/SyntaxTree/BasicType.cs
mbasic/SyntaxTree/Randomize.cs
mbasic/SyntaxTree/VariableReference.cs
mbasic/Variable.cs
samples/secret.mbas [new file with mode: 0644]

index a56fc4a..67628b2 100644 (file)
@@ -271,13 +271,9 @@ namespace mbasic
             index = symbols.Lookup(value);
             if (index == -1)
             {
-                BasicType basicType = (value.Contains("$") ? BasicType.String : BasicType.Number);
-                index = symbols.Insert(value, basicType);
+                index = symbols.Insert(value);
             }
             return Token.Variable;
-
-
-
         }
 
         private Token NextString(bool quoted)
index f72ff26..9851c2c 100644 (file)
@@ -186,6 +186,7 @@ namespace mbasic
             while (lookahead != Token.EOF && lookahead != Token.EndOfLine)
             {
                 int symbolIndex = lexer.SymbolIndex;
+                symbols[symbolIndex].ConstrainType();
                 switch (symbols[symbolIndex].BasicType)
                 {
                     case BasicType.Number:
@@ -291,6 +292,7 @@ namespace mbasic
                 inputPrompt = new StringLiteral("? ", LineId.None);
                 VariableReference vr = (VariableReference)expr; // The expr must have been a Variable Reference
                 int symbolIndex = vr.SymbolIndex;
+                symbols[symbolIndex].ConstrainType();
                 switch (symbols[symbolIndex].BasicType)
                 {
                     case BasicType.Number:
@@ -307,6 +309,7 @@ namespace mbasic
             while (lookahead != Token.EOF && lookahead != Token.EndOfLine)
             {
                 int symbolIndex = lexer.SymbolIndex;
+                symbols[symbolIndex].ConstrainType();
                 switch (symbols[symbolIndex].BasicType)
                 {
                     case BasicType.Number:
index f7c69fa..3184707 100644 (file)
@@ -49,6 +49,7 @@ namespace mbasic
             string moduleName = assemblyName + ".exe";
             string exeName = assemblyName + ".exe";
 
+            fileName = Path.GetFullPath(fileName);
             Stream stream = File.OpenRead(fileName);
             SymbolTable symbols = new SymbolTable();
             InitializeReservedWords(symbols);
@@ -84,11 +85,16 @@ namespace mbasic
             MethodBuilder mthdbldr = typeBuilder.DefineMethod("Main", MethodAttributes.Static | MethodAttributes.Public);
 
             ILGenerator gen = mthdbldr.GetILGenerator();
-            // Create global variables
+            Node.writer = mbldr.DefineDocument(fileName, Guid.Empty, Guid.Empty, Guid.Empty);
+            Node.debug = debug;
+            Node.labels = new LabelList();
+
+            n.CheckTypes();
+            // Create local variables
 
             List<LocalBuilder> locals = new List<LocalBuilder>();
-               
-            foreach(Variable v in symbols.Variables)
+
+            foreach (Variable v in symbols.Variables)
             {
                 LocalBuilder local;
                 if (v.BasicType == BasicType.String) locals.Add(local = gen.DeclareLocal(typeof(string)));
@@ -96,11 +102,8 @@ namespace mbasic
                 if (debug) local.SetLocalSymInfo(v.Value);
             }
             Node.locals = locals;
-            Node.writer = mbldr.DefineDocument(fileName, Guid.Empty, Guid.Empty, Guid.Empty);
-            Node.debug = debug;
-            Node.labels = new LabelList();
 
-            n.CheckTypes();
+
             n.RecordLabels(gen);
 
             #region Initialize strings to String.Empty
index 51492b7..e6cc4ed 100644 (file)
@@ -39,9 +39,9 @@ namespace mbasic
         /// </summary>
         /// <param name="s"></param>
         /// <param name="t"></param>
-        public int Insert(string name, BasicType basicType)
+        public int Insert(string name)
         {
-            variables.Add(new Variable(name, basicType));
+            variables.Add(new Variable(name));
             return variables.Count - 1;
         }
 
index 565d436..04df796 100644 (file)
@@ -55,10 +55,9 @@ namespace mbasic.SyntaxTree
 
         public override void CheckTypes()
         {
-            Type varType = locals[localIndex].LocalType;
-            BasicType varBasicType;
-            if (varType == typeof(string)) varBasicType = BasicType.String;
-            else varBasicType = BasicType.Number;
+            Variable var = symbols[localIndex];
+            var.ConstrainType();
+            BasicType varBasicType = var.BasicType;
 
             valueType = value.GetBasicType();
 
index f9bcfd6..6ee4b1f 100644 (file)
@@ -23,8 +23,11 @@ namespace mbasic.SyntaxTree
 {
     enum BasicType
     {
+        Unknown,
         Number,
+        NumberArray,
         String,
+        StringArray,
         Boolean,    // Not really a TiBasic type, but one used for optimization. A user will never "see" one of these.
         Error
     }
index 205d4fc..a5b022d 100644 (file)
@@ -54,9 +54,12 @@ namespace mbasic.SyntaxTree
 
         public override void CheckTypes()
         {
-            exprType = seedExpression.GetBasicType();
-            if (exprType == BasicType.Number || exprType == BasicType.Boolean) return;
-            throw new Exception("Type error");
+            if (seedSpecified)
+            {
+                exprType = seedExpression.GetBasicType();
+                if (exprType == BasicType.Number || exprType == BasicType.Boolean) return;
+                throw new Exception("Type error");
+            }
         }
 
         public override void Emit(ILGenerator gen)
index e992a94..1ed2a18 100644 (file)
@@ -69,7 +69,9 @@ namespace mbasic.SyntaxTree
 
         public override BasicType GetBasicType()
         {
-            return symbols[index].BasicType;
+            Variable var = symbols[index];
+            if (var.BasicType == BasicType.Unknown) var.SetBasicType();
+            return var.BasicType;
         }
     }
 }
index 0598013..1d54bab 100644 (file)
@@ -30,13 +30,37 @@ namespace mbasic
     {
         string value;
         BasicType dataType; // The TI BASIC data type
-        public Variable(string val, BasicType dataType)
+        public Variable(string val)
         {
             this.value = val;
-            this.dataType = dataType;
+            this.dataType = BasicType.Unknown;
         }
 
         public BasicType BasicType { get { return dataType; } }
+        public void SetBasicType(bool isArray)
+        {
+            if (isArray) throw new ArgumentException("arrays not yet supported");
+            if (dataType == BasicType.Unknown)
+                dataType = (value.Contains("$") ? BasicType.String : BasicType.Number);
+            else
+                throw new InvalidOperationException("Data type already set");
+        }
+
+        public void SetBasicType()
+        {
+            SetBasicType(false);
+        }
+
+        public void ConstrainType(bool isArray)
+        {
+            if (dataType == BasicType.Unknown) SetBasicType(isArray);
+        }
+
+        public void ConstrainType()
+        {
+            ConstrainType(false);
+        }
+
         public string Value { get { return value; } }
     }
 }
diff --git a/samples/secret.mbas b/samples/secret.mbas
new file mode 100644 (file)
index 0000000..8793ca6
--- /dev/null
@@ -0,0 +1,36 @@
+110 RANDOMIZE\r
+120 MSG1$ = "SECRET NUMBER IS"\r
+130 MSG2$ = "YOUR NUMBER"\r
+\r
+140 CALL CLEAR\r
+\r
+150 INPUT "ENTER LIMIT: ":LIMIT\r
+160 SECRET = INT(LIMIT*RND)+1\r
+170 CALL CLEAR\r
+180 N=N+1\r
+\r
+190 INPUT "GUESS: ":GUESS\r
+\r
+210 IF SECRET=GUESS THEN 300\r
+220 IF SECRET<GUESS THEN 260 ELSE 280\r
+\r
+240 PRINT MSG1$&" BETWEEN":MSG2$\r
+250 GOTO 180\r
+260 PRINT MSG1$&" LESS THAN" : MSG2$\r
+270 GOTO 180\r
+280 PRINT MSG1$&" LARGER THAN": MSG2$\r
+290 GOTO 180\r
+300 PRINT "YOU GUESSED THE SECRET"\r
+310 PRINT "NUMBER IN";N;"TRIES"\r
+\r
+320 PRINT "WANT TO PLAY AGAIN?"\r
+330 INPUT "ENTER Y OR N: ":A$\r
+340 IF A$<>"Y" THEN 390\r
+350 N=0\r
+360 PRINT "WANT TO SET A NEW LIMIT?"\r
+370 INPUT "ENTER Y OR N: ":B$\r
+380 IF B$="Y" THEN 140 \r
+381 GOTO 160\r
+390 PRINT "DONE"\r
+\r
+\r