syntax: allow untyped variable declaration
authorJean Privat <jean@pryen.org>
Thu, 20 Aug 2009 02:29:55 +0000 (22:29 -0400)
committerJean Privat <jean@pryen.org>
Thu, 20 Aug 2009 02:29:55 +0000 (22:29 -0400)
It means there is now a distinction between variables with a null static
type because of a previous error and untyped variables that also have null
static type. So introduce Variable::is_typed.

Enhance check_is_set with untyped variable verification.

Compile untyped variable as 'nullable Object' registers.

Signed-off-by: Jean Privat <jean@pryen.org>

14 files changed:
src/syntax/control_flow.nit
src/syntax/icode_generation.nit
src/syntax/syntax_base.nit
src/syntax/typing.nit
tests/base_var_untyped.nit [new file with mode: 0644]
tests/sav/base_var_untyped.sav [new file with mode: 0644]
tests/sav/base_var_untyped_alt1.sav [new file with mode: 0644]
tests/sav/base_var_untyped_alt2.sav [new file with mode: 0644]
tests/sav/base_var_untyped_alt3.sav [new file with mode: 0644]
tests/sav/base_var_untyped_alt4.sav [new file with mode: 0644]
tests/sav/base_var_untyped_alt5.sav [new file with mode: 0644]
tests/sav/base_var_untyped_alt6.sav [new file with mode: 0644]
tests/sav/base_var_untyped_alt7.sav [new file with mode: 0644]
tests/sav/base_var_untyped_alt8.sav [new file with mode: 0644]

index 4b8d0fc..dd3ca06 100644 (file)
@@ -53,6 +53,8 @@ abstract class VariableContext
        do
                if v.must_be_set and not is_set(v) then
                        _visitor.error(n, "Error: variable '{v}' is possibly unset.")
+               else if v.is_typed and stype(v) == null then
+                       _visitor.error(n, "Error: variable '{v}' is untyped.")
                end
        end
 
index fab9e98..fb4a801 100644 (file)
@@ -58,7 +58,9 @@ special ICodeBuilder
                if _variables.has_key(v) then
                        return _variables[v]
                else
-                       var reg = new_register(v.stype.as(not null))
+                       var t = v.stype
+                       if t == null then t = visitor.type_object.as_nullable
+                       var reg = new_register(t)
                        _variables[v] = reg
                        return reg
                end
index 512ccf4..13e1372 100644 (file)
@@ -229,7 +229,12 @@ abstract class Variable
        # Declaration AST node
        readable var _decl: nullable ANode
 
-       # Static type
+       # Is the variable correcly declared
+       # Return false if typed was not yet computed or
+       # if an error occured during the typing computation
+       fun is_typed: Bool do return _stype != null
+
+       # The declaration static type of the variable
        readable writable var _stype: nullable MMType
 
        redef fun to_s do return _name.to_s
index fb4c838..c3a5ffc 100644 (file)
@@ -136,6 +136,9 @@ special AbsSyntaxVisitor
        end
 end
 
+redef class VarVariable
+       redef readable var _is_typed: Bool = false
+end
 
 ###############################################################################
 
@@ -353,18 +356,20 @@ redef class AVardeclExpr
                var va = new VarVariable(n_id.to_symbol, n_id)
                _variable = va
                v.variable_ctx.add(va)
-               if n_expr != null then v.variable_ctx.mark_is_set(va)
+               var ne = n_expr
+               if ne != null then v.variable_ctx.mark_is_set(va)
 
                if n_type != null then
                        if not n_type.is_typed then return
                        va.stype = n_type.stype
-                       if n_expr != null then
-                               v.check_conform_expr(n_expr.as(not null), va.stype)
+                       if ne != null then
+                               v.check_conform_expr(ne, va.stype)
                        end
-               else
-                       if not v.check_expr(n_expr.as(not null)) then return
+               else if ne != null then
+                       if not v.check_expr(ne) then return
                        va.stype = n_expr.stype
                end
+               va._is_typed = true
                _is_typed = true
        end
 end
diff --git a/tests/base_var_untyped.nit b/tests/base_var_untyped.nit
new file mode 100644 (file)
index 0000000..e7a4a6a
--- /dev/null
@@ -0,0 +1,58 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2009 Jean Privat <jean@pryen.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+fun rand: Bool do return true
+
+var a
+#alt1#a.output
+a = 1
+(a*10).output
+a = 2
+(a*10).output
+a = false
+(not a).output
+
+var b1
+var b2
+var b3
+if rand then
+       b1 = 3
+       b2 = 4
+       b3 = 5
+else
+       b1 = -3
+       b2 = true
+end
+(b1*10).output
+#alt2#b2.output
+#alt3#b3.output
+#alt4#b2 += 1
+
+var c
+while rand do
+       c = 4
+       #alt5#c = b2
+       #alt6#c = b3
+       (c*10).output
+       if rand then break
+end
+#alt7#c.output
+
+var d
+#alt8#d = fail
+#alt8#d.output
diff --git a/tests/sav/base_var_untyped.sav b/tests/sav/base_var_untyped.sav
new file mode 100644 (file)
index 0000000..ed4f859
--- /dev/null
@@ -0,0 +1,5 @@
+10
+20
+true
+30
+40
diff --git a/tests/sav/base_var_untyped_alt1.sav b/tests/sav/base_var_untyped_alt1.sav
new file mode 100644 (file)
index 0000000..6ec044f
--- /dev/null
@@ -0,0 +1 @@
+alt/base_var_untyped_alt1.nit:22,1: Error: variable 'a' is possibly unset.
diff --git a/tests/sav/base_var_untyped_alt2.sav b/tests/sav/base_var_untyped_alt2.sav
new file mode 100644 (file)
index 0000000..a5c54ef
--- /dev/null
@@ -0,0 +1 @@
+alt/base_var_untyped_alt2.nit:42,1--2: Error: variable 'b2' is untyped.
diff --git a/tests/sav/base_var_untyped_alt3.sav b/tests/sav/base_var_untyped_alt3.sav
new file mode 100644 (file)
index 0000000..dc1fe07
--- /dev/null
@@ -0,0 +1 @@
+alt/base_var_untyped_alt3.nit:43,1--2: Error: variable 'b3' is possibly unset.
diff --git a/tests/sav/base_var_untyped_alt4.sav b/tests/sav/base_var_untyped_alt4.sav
new file mode 100644 (file)
index 0000000..a18278f
--- /dev/null
@@ -0,0 +1 @@
+alt/base_var_untyped_alt4.nit:44,1--7: Error: variable 'b2' is untyped.
diff --git a/tests/sav/base_var_untyped_alt5.sav b/tests/sav/base_var_untyped_alt5.sav
new file mode 100644 (file)
index 0000000..892ac1b
--- /dev/null
@@ -0,0 +1 @@
+alt/base_var_untyped_alt5.nit:49,6--7: Error: variable 'b2' is untyped.
diff --git a/tests/sav/base_var_untyped_alt6.sav b/tests/sav/base_var_untyped_alt6.sav
new file mode 100644 (file)
index 0000000..798387e
--- /dev/null
@@ -0,0 +1 @@
+alt/base_var_untyped_alt6.nit:50,6--7: Error: variable 'b3' is possibly unset.
diff --git a/tests/sav/base_var_untyped_alt7.sav b/tests/sav/base_var_untyped_alt7.sav
new file mode 100644 (file)
index 0000000..d5c703d
--- /dev/null
@@ -0,0 +1 @@
+alt/base_var_untyped_alt7.nit:54,1: Error: variable 'c' is possibly unset.
diff --git a/tests/sav/base_var_untyped_alt8.sav b/tests/sav/base_var_untyped_alt8.sav
new file mode 100644 (file)
index 0000000..b4cd0ba
--- /dev/null
@@ -0,0 +1,2 @@
+alt/base_var_untyped_alt8.nit:57,5--8: Error: Method or variable 'fail' unknown in Sys.
+alt/base_var_untyped_alt8.nit:58,1: Error: variable 'd' is untyped.