nullable: type, compile and test 'as(not null)'
authorJean Privat <jean@pryen.org>
Fri, 12 Jun 2009 14:59:28 +0000 (10:59 -0400)
committerJean Privat <jean@pryen.org>
Wed, 24 Jun 2009 20:01:53 +0000 (16:01 -0400)
Signed-off-by: Jean Privat <jean@pryen.org>

src/compiling/compiling_methods.nit
src/syntax/typing.nit
tests/base_as_notnull.nit [new file with mode: 0644]
tests/sav/base_as_notnull.sav [new file with mode: 0644]
tests/sav/base_as_notnull_alt1.sav [new file with mode: 0644]
tests/sav/base_as_notnull_alt2.sav [new file with mode: 0644]
tests/sav/base_as_notnull_alt3.sav [new file with mode: 0644]
tests/sav/base_as_notnull_alt4.sav [new file with mode: 0644]
tests/sav/base_as_notnull_alt5.sav [new file with mode: 0644]
tests/sav/base_as_notnull_alt6.sav [new file with mode: 0644]
tests/sav/base_as_notnull_alt7.sav [new file with mode: 0644]

index a8bbd6d..935b3d0 100644 (file)
@@ -629,6 +629,14 @@ redef class MMType
                var g = local_class.global
                v.add_instr("if (({recv}!=NIT_NULL) && !VAL_ISA({recv}, {g.color_id}, {g.id_id})) \{ fprintf(stderr, \"Cast failled\"); {v.printf_locate_error(n)} nit_exit(1); } /*cast {self}*/;")
        end
+
+       # Compile a notnull cast assertion
+       meth compile_notnull_check(v: CompilerVisitor, recv: String, n: PNode)
+       do
+               if is_nullable then
+                       v.add_instr("if (({recv}==NIT_NULL)) \{ fprintf(stderr, \"Cast failled\"); {v.printf_locate_error(n)} nit_exit(1); } /*cast {self}*/;")
+               end
+       end
 end
 
 ###############################################################################
@@ -1230,6 +1238,15 @@ redef class AAsCastExpr
        end
 end
 
+redef class AAsNotnullExpr
+       redef meth compile_expr(v)
+       do
+               var e = v.compile_expr(n_expr)
+               n_expr.stype.compile_notnull_check(v, e, self)
+               return e
+       end
+end
+
 redef class ATrueExpr
        redef meth compile_expr(v)
        do
index 421b433..ff61191 100644 (file)
@@ -1560,6 +1560,22 @@ special ATypeCheckExpr
        end
 end
 
+redef class AAsNotnullExpr
+       redef meth after_typing(v)
+       do
+               if not v.check_expr(n_expr) then return
+               var t = n_expr.stype
+               if t isa MMTypeNone then
+                       v.error(n_expr, "Type error: 'as(not null)' on 'null' value.")
+                       return
+               else if not t.is_nullable then
+                       v.warning(n_expr, "Warning: 'as(not null)' on non nullable type.")
+               end
+               _stype = n_expr.stype.as_notnull
+               _is_typed = true
+       end
+end
+
 redef class AProxyExpr
        redef meth after_typing(v)
        do
diff --git a/tests/base_as_notnull.nit b/tests/base_as_notnull.nit
new file mode 100644 (file)
index 0000000..aee5acb
--- /dev/null
@@ -0,0 +1,61 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2005-2008 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
+
+class A
+       attr _i: Int
+       redef meth output do _i.output
+       init(i: Int) do _i = i
+end
+
+class B
+special A
+end
+
+meth outa(a: A) do a.output
+meth outb(b: B) do b.output
+
+var a: A = new A(1)
+var ab: A = new B(2)
+var b: B = new B(3)
+var na: nullable A = new A(4)
+var nab: nullable A = new B(5)
+var nb: nullable B = new B(6)
+var nan: nullable A = null
+var nbn: nullable B = null
+
+outa(a.as(not null))
+outa(ab.as(not null))
+outa(b.as(not null))
+outa(na.as(not null))
+outa(nab.as(not null))
+outa(nb.as(not null))
+
+'\n'.output
+
+#alt1#outb(a.as(not null))
+#alt2#outb(ab.as(not null))
+outb(b.as(not null))
+#alt3#outb(na.as(not null))
+#alt4#outb(nab.as(not null))
+outb(nb.as(not null))
+
+'\n'.output
+
+#alt5#nan.as(not null).output
+#alt6#nbn.as(not null).output
+#alt7#null.as(not null).output
diff --git a/tests/sav/base_as_notnull.sav b/tests/sav/base_as_notnull.sav
new file mode 100644 (file)
index 0000000..8f499ee
--- /dev/null
@@ -0,0 +1,10 @@
+1
+2
+3
+4
+5
+6
+
+3
+6
+
diff --git a/tests/sav/base_as_notnull_alt1.sav b/tests/sav/base_as_notnull_alt1.sav
new file mode 100644 (file)
index 0000000..d50a4c4
--- /dev/null
@@ -0,0 +1 @@
+alt/base_as_notnull_alt1.nit:50,6--18: Type error: expected B, got A
diff --git a/tests/sav/base_as_notnull_alt2.sav b/tests/sav/base_as_notnull_alt2.sav
new file mode 100644 (file)
index 0000000..6f7787c
--- /dev/null
@@ -0,0 +1 @@
+alt/base_as_notnull_alt2.nit:51,6--19: Type error: expected B, got A
diff --git a/tests/sav/base_as_notnull_alt3.sav b/tests/sav/base_as_notnull_alt3.sav
new file mode 100644 (file)
index 0000000..6d6b636
--- /dev/null
@@ -0,0 +1 @@
+alt/base_as_notnull_alt3.nit:53,6--19: Type error: expected B, got A
diff --git a/tests/sav/base_as_notnull_alt4.sav b/tests/sav/base_as_notnull_alt4.sav
new file mode 100644 (file)
index 0000000..e6a304d
--- /dev/null
@@ -0,0 +1 @@
+alt/base_as_notnull_alt4.nit:54,6--20: Type error: expected B, got A
diff --git a/tests/sav/base_as_notnull_alt5.sav b/tests/sav/base_as_notnull_alt5.sav
new file mode 100644 (file)
index 0000000..b246a71
--- /dev/null
@@ -0,0 +1,14 @@
+1
+2
+3
+4
+5
+6
+
+3
+6
+
+Cast failled in base_as_notnull_alt5::Sys::(kernel::Sys::main) (alt/base_as_notnull_alt5.nit:59)
+,---- Stack trace -- - -  -
+| base_as_notnull_alt5::Sys::(kernel::Sys::main) (alt/base_as_notnull_alt5.nit:32)
+`------------------- - -  -
diff --git a/tests/sav/base_as_notnull_alt6.sav b/tests/sav/base_as_notnull_alt6.sav
new file mode 100644 (file)
index 0000000..12af462
--- /dev/null
@@ -0,0 +1,14 @@
+1
+2
+3
+4
+5
+6
+
+3
+6
+
+Cast failled in base_as_notnull_alt6::Sys::(kernel::Sys::main) (alt/base_as_notnull_alt6.nit:60)
+,---- Stack trace -- - -  -
+| base_as_notnull_alt6::Sys::(kernel::Sys::main) (alt/base_as_notnull_alt6.nit:32)
+`------------------- - -  -
diff --git a/tests/sav/base_as_notnull_alt7.sav b/tests/sav/base_as_notnull_alt7.sav
new file mode 100644 (file)
index 0000000..95af7ae
--- /dev/null
@@ -0,0 +1 @@
+alt/base_as_notnull_alt7.nit:61,1--4: Type error: 'as(not null)' on 'null' value.