Merge: Augmented literal strings
[nit.git] / src / interpreter / naive_interpreter.nit
index e1ca2df..9236d99 100644 (file)
@@ -328,6 +328,16 @@ class NaiveInterpreter
                return instance
        end
 
+       # Return a new native string initialized with `txt`
+       fun native_string_instance_from_ns(txt: NativeString, len: Int): Instance
+       do
+               var instance = native_string_instance_len(len)
+               var val = instance.val
+               txt.copy_to(val, len, 0, 0)
+
+               return instance
+       end
+
        # Return a new native string initialized of `length`
        fun native_string_instance_len(length: Int): PrimitiveInstance[NativeString]
        do
@@ -1002,9 +1012,6 @@ redef class AMethPropdef
                                return v.int32_instance(recvval.to_i32)
                        else if pname == "to_u32" then
                                return v.uint32_instance(recvval.to_u32)
-                       else if pname == "rand" then
-                               var res = recvval.rand
-                               return v.int_instance(res)
                        end
                else if cname == "Byte" then
                        var recvval = args[0].to_b
@@ -1130,8 +1137,6 @@ redef class AMethPropdef
                                return v.float_instance(args[0].to_f.log)
                        else if pname == "pow" then
                                return v.float_instance(args[0].to_f.pow(args[1].to_f))
-                       else if pname == "rand" then
-                               return v.float_instance(args[0].to_f.rand)
                        else if pname == "abs" then
                                return v.float_instance(args[0].to_f.abs)
                        else if pname == "hypot_with" then
@@ -1497,7 +1502,12 @@ redef class AAttrPropdef
                        return evaluate_expr(v, recv, f)
                else if mpropdef == mwritepropdef then
                        assert args.length == 2
-                       v.write_attribute(attr, recv, args[1])
+                       var arg = args[1]
+                       if is_optional and arg.mtype isa MNullType then
+                               var f = v.new_frame(self, mpropdef, args)
+                               arg = evaluate_expr(v, recv, f)
+                       end
+                       v.write_attribute(attr, recv, arg)
                        return null
                else
                        abort
@@ -1553,14 +1563,14 @@ end
 
 redef class AClassdef
        # Execute an implicit `mpropdef` associated with the current node.
-       private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
+       private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance]): nullable Instance
        do
                if mpropdef.mproperty.is_root_init then
-                       assert args.length == 1
+                       assert arguments.length == 1
                        if not mpropdef.is_intro then
                                # standard call-next-method
-                               var superpd = mpropdef.lookup_next_definition(v.mainmodule, args.first.mtype)
-                               v.call(superpd, args)
+                               var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
+                               v.call(superpd, arguments)
                        end
                        return null
                else
@@ -1833,7 +1843,13 @@ redef class AWithExpr
                v.callsite(method_start, [expr])
                v.stmt(self.n_block)
                v.is_escape(self.break_mark) # Clear the break
+
+               # Execute the finally without an escape
+               var old_mark = v.escapemark
+               v.escapemark = null
                v.callsite(method_finish, [expr])
+               # Restore the escape unless another escape was provided
+               if v.escapemark == null then v.escapemark = old_mark
        end
 end
 
@@ -1929,6 +1945,8 @@ end
 redef class ACharExpr
        redef fun expr(v)
        do
+               if is_ascii then return v.byte_instance(self.value.as(not null).ascii)
+               if is_code_point then return v.int_instance(self.value.as(not null).code_point)
                return v.char_instance(self.value.as(not null))
        end
 end
@@ -1955,11 +1973,71 @@ redef class AArrayExpr
        end
 end
 
+redef class AugmentedStringFormExpr
+       # Factorize the making of a `Regex` object from a literal prefixed string
+       fun make_re(v: NaiveInterpreter, rs: Instance): nullable Instance do
+               var tore = to_re
+               assert tore != null
+               var res = v.callsite(tore, [rs])
+               if res == null then
+                       print "Cannot call property `to_re` on {self}"
+                       abort
+               end
+               for j in suffix.chars do
+                       if j == 'i' then
+                               var prop = ignore_case
+                               assert prop != null
+                               v.callsite(prop, [res, v.bool_instance(true)])
+                               continue
+                       end
+                       if j == 'm' then
+                               var prop = newline
+                               assert prop != null
+                               v.callsite(prop, [res, v.bool_instance(true)])
+                               continue
+                       end
+                       if j == 'b' then
+                               var prop = extended
+                               assert prop != null
+                               v.callsite(prop, [res, v.bool_instance(false)])
+                               continue
+                       end
+                       # Should not happen, this needs to be updated
+                       # along with the addition of new suffixes
+                       abort
+               end
+               return res
+       end
+end
+
 redef class AStringFormExpr
-       redef fun expr(v)
-       do
-               var txt = self.value.as(not null)
-               return v.string_instance(txt)
+       redef fun expr(v) do return v.string_instance(value)
+end
+
+redef class AStringExpr
+       redef fun expr(v) do
+               var s = v.string_instance(value)
+               if is_string then return s
+               if is_bytestring then
+                       var ns = v.native_string_instance_from_ns(bytes.items, bytes.length)
+                       var ln = v.int_instance(bytes.length)
+                       var prop = to_bytes_with_copy
+                       assert prop != null
+                       var res = v.callsite(prop, [ns, ln])
+                       if res == null then
+                               print "Cannot call property `to_bytes` on {self}"
+                               abort
+                       end
+                       s = res
+               else if is_re then
+                       var res = make_re(v, s)
+                       assert res != null
+                       s = res
+               else
+                       print "Unimplemented prefix or suffix for {self}"
+                       abort
+               end
+               return s
        end
 end
 
@@ -1975,6 +2053,7 @@ redef class ASuperstringExpr
                var i = v.array_instance(array, v.mainmodule.object_type)
                var res = v.send(v.force_get_primitive_method("plain_to_s", i.mtype), [i])
                assert res != null
+               if is_re then res = make_re(v, res)
                return res
        end
 end