Before this PR `./` was simplified in `/` which was wrong.
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>
Pull-Request: #1368
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.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.
+
+# Services to manipulate `Date`, `Time` and `DateTime`
+#
+# The services are split in 2 classes:
+#
+# * `Date` handles the year, month and day parts of the date.
+# * `Time` handles the time in hours, minutes and seconds.
+#
+# These are united in `DateTime` for a precise time in a precise day.
+#
+# ~~~
+# var now = new Time.now
+# var midnight = new Time(0, 0, 0)
+# assert now > midnight
+#
+# var nine_thirty = new Time(9, 30, 0)
+# var eleven_twenty = new Time(11, 20, 0)
+# assert eleven_twenty > nine_thirty
+#
+# var pi_day = new Date(2015, 03, 14)
+# var may_the_fourth = new Date(2015, 5, 4)
+# assert pi_day < may_the_fourth
+#
+# var now_t = new DateTime.now
+# var epoch = new DateTime(1970, 1, 1, 0, 0, 0)
+# assert now_t > epoch
+# ~~~
+#
+module date
+
+# A time of the day, composed of an `hour`, a `minute` and a `second` count
+class Time
+ super Comparable
+ redef type OTHER: Time
+
+ # The hour part of this time, between 0 and 23
+ var hour: Int
+
+ # The minute within the hour, between 0 and 59
+ var minute: Int
+
+ # The second within the minute, between 0 and 59
+ var second: Int
+
+ # Get the current time of the day
+ init now do
+ var tm = new Tm.localtime
+ hour = tm.hour
+ minute = tm.min
+ second = tm.sec
+ end
+
+ # Get the difference between two times in second
+ fun diff_time(other: Time): Int do
+ return (hour * 3600 + minute * 60 + second) -
+ (other.hour * 3600 + other.minute * 60 + other.second)
+ end
+
+ redef fun ==(d) do return d isa Time and time_eq(d)
+
+ redef fun <(d) do return self.diff_time(d) < 0
+
+ redef fun hash do return hour * 1024 + minute * 64 + second
+
+ private fun time_eq(other: Time): Bool
+ do
+ return hour * 3600 + minute * 60 + second ==
+ other.hour * 3600 + other.minute * 60 + other.second
+ end
+end
+
+# A date, composed by a `year`, a `month` and a `day`
+class Date
+ super Comparable
+ redef type OTHER: Date
+
+ # Year, ex: 1989
+ var year: Int
+
+ # Month as an integer, `1` for January, `2` for February, etc.
+ var month: Int
+
+ # Day of the month
+ var day: Int
+
+ # UTC time zone
+ #
+ # FIXME this value is not yet applied
+ var time_zone = "Z"
+
+ # The date of this day
+ init today do
+ var tm = new Tm.localtime
+ year = 1900 + tm.year
+ month = tm.mon + 1
+ day = tm.mday
+ end
+
+ # `self` formatted according to ISO 8601
+ redef fun to_s do return "{year}-{month}-{day}"
+
+ # Difference in days between `self` and `other`
+ fun diff_days(other: Date): Int
+ do
+ var y_out = year - other.year
+ y_out = y_out * 365
+ var m_out = month - other.month
+ m_out = m_out * 30 # FIXME
+ return day - other.day + m_out + y_out
+ end
+
+ # Difference in months between `self` and `other`
+ fun diff_months(other: Date): Int
+ do
+ var y_out = year - other.year
+ y_out = y_out * 12
+ return month - other.month + y_out
+ end
+
+ # Difference in years between `self` and `other`
+ fun diff_years(other: Date): Int do return year - other.year
+
+ redef fun ==(d) do return d isa Date and self.diff_days(d) == 0
+
+ redef fun hash do return year + month * 1024 + day * 2048
+
+ redef fun <(d) do return self.diff_days(d) < 0
+
+ # Is `self` is between the years of `a` and `b`?
+ private fun is_between_years(a, b: Date): Bool
+ do
+ return (a.year > year and b.year < year) or (b.year > year and a.year < year) or (a.year == year or b.year == year)
+ end
+
+ # Is `self` is between the months of `a` and `b`?
+ private fun is_between_months(a, b: Date) : Bool
+ do
+ if not self.is_between_years(a,b) then return false
+ return (a.month > month and b.month < month) or (b.month > month and a.month < month) or (a.month == month or b.month == month)
+ end
+
+ # Is `self` between `a` and `b`?
+ redef fun is_between(a, b)
+ do
+ if not self.is_between_months(a, b) then return false
+ return (a.day > day and b.day < day) or (b.day > day and a.day < day) or (a.day == day or b.day == day)
+ end
+end
+
+# A `Time` in a `Date`
+class DateTime
+ super Date
+ super Time
+ redef type OTHER: DateTime
+ autoinit year, month, day, hour, minute, second
+
+ # Get the current `DateTime`
+ init now
+ do
+ super
+ today
+ end
+
+ redef fun ==(other) do return other isa DateTime and diff_days(other) == 0 and time_eq(other)
+
+ redef fun to_s do return "{super} {hour}:{minute}:{second}{time_zone}"
+end
# files to compile TODO check is appropriate
var files = new Array[String]
- # Add `c_function` as a `static` function local to this unit
+ # Add a `static` `c_function` to be strictly local to this unit
fun add_local_function(c_function: CFunction)
do
body_decl.add "static {c_function.signature};\n"
body_impl.add c_function.to_writer
end
- # Add `c_function` as a public function to this unit
+ # Add a public `c_function` accessible from outside this compilation unit
fun add_exported_function(c_function: CFunction)
do
- header_decl.add "{c_function.signature};\n"
+ body_decl.add "{c_function.signature};\n"
body_impl.add "\n"
body_impl.add c_function.to_writer
end
if nexpr == null then return
if nexpr.mtype == null and not nexpr.is_typed then
# Untyped expression.
- # Might mean dead code
- # So just return
+ # Might mean dead code or invalid code
+ # so aborts
+ add_abort("FATAL: bad statement executed.")
return
end
do
if nexpr.mtype == null then
# Untyped expression.
- # Might mean dead code
- # so return a placebo result
+ # Might mean dead code or invalid code.
+ # so aborts
+ add_abort("FATAL: bad expression executed.")
+ # and return a placebo result to please the C compiler
if mtype == null then mtype = compiler.mainmodule.object_type
return new_var(mtype)
end
for cd in mmodule.mclassdefs do
for pd in cd.mpropdefs do
if not pd isa MMethodDef then continue
+ if pd.msignature == null then continue # Skip broken method
var rta = runtime_type_analysis
if modelbuilder.toolcontext.opt_skip_dead_methods.value and rta != null and not rta.live_methoddefs.has(pd) then continue
#print "compile {pd} @ {cd} @ {mmodule}"
private fun insert_compiler_options
do
cflags.add_one("", "-I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux/")
- ldflags.add_one("", "-L $(JNI_LIB_PATH) -ljvm")
end
# Name of the generated Java class where to store all implementation methods of this module
do
toolcontext.warning(node.hot_location, tag, msg)
end
+
+ # Issue a warning if `sub` is a standalone `do` block.
+ fun check_do_expr(sub: nullable AExpr)
+ do
+ if sub isa ADoExpr then
+ warning(sub, "useless-do", "Warning: superfluous `do` block.")
+ end
+ end
end
else
n_expr.warn_parentheses(v)
end
+ v.check_do_expr(n_block)
+ end
+end
+
+redef class ADoExpr
+ redef fun after_simple_misc(v)
+ do
+ v.check_do_expr(n_block)
+ end
+end
+
+redef class ALoopExpr
+ redef fun after_simple_misc(v)
+ do
+ v.check_do_expr(n_block)
end
end
redef fun after_simple_misc(v)
do
n_expr.warn_parentheses(v)
+ v.check_do_expr(n_block)
+ end
+end
+
+redef class AWithExpr
+ redef fun after_simple_misc(v)
+ do
+ v.check_do_expr(n_block)
end
end
end
var nit_dir = toolcontext.nit_dir
- var libname = "{nit_dir}/lib"
+ var libname = nit_dir/"lib"
+ if libname.file_exists then paths.add(libname)
+ libname = nit_dir/"contrib"
if libname.file_exists then paths.add(libname)
end
return res
end
+ # Fourth, try if the requested module is itself a group with a src
+ try_file = dirname + "/" + name + "/src/" + name + ".nit"
+ if try_file.file_exists then
+ var res = self.identify_file(try_file.simplify_path)
+ assert res != null
+ return res
+ end
+
c = c.parent
end
end
end
end
+ try_file = (dirname + "/" + name + "/src/" + name + ".nit").simplify_path
+ if try_file.file_exists then
+ if candidate == null then
+ candidate = try_file
+ else if candidate != try_file then
+ # try to disambiguate conflicting modules
+ var abs_candidate = module_absolute_path(candidate)
+ var abs_try_file = module_absolute_path(try_file)
+ if abs_candidate != abs_try_file then
+ toolcontext.error(location, "Error: conflicting module file for `{name}`: `{candidate}` `{try_file}`")
+ end
+ end
+ end
end
if candidate == null then return null
return identify_file(candidate)
# Representation of this type in C for the internal of the system
# Hides extern types.
- fun cname_blind: String is abstract
+ fun cname_blind: String do return "struct nitni_instance *"
# Representation of this type in mangled C
# Object -> Object
# Pointer -> Pointer
fun mangled_cname: String is abstract
- # Does this types has a primitive reprensentation
+ # Does this type have a primitive representation?
+ #
# type Object is_primitive? false
# type Pointer is_primitive? true
fun is_cprimitive: Bool is abstract
if name == "Byte" then return "unsigned char"
if name == "NativeString" then return "unsigned char*"
if mclass.kind == extern_kind then return "void*"
- return "struct nitni_instance *"
+ return super
end
# Name of this type in C for normal classes (not extern and not primitive)
redef fun mangled_cname do return mclass.name
redef fun is_cprimitive do return mclass.kind == extern_kind or
- (once ["Bool", "Char", "Float", "Int", "NativeString"]).has(mclass.name)
+ (once ["Bool", "Char", "Float", "Int", "NativeString", "Byte"]).has(mclass.name)
end
redef class MNullableType
redef fun cname do return mangled_cname
- redef fun cname_blind do return "struct nitni_instance *"
redef fun mangled_cname do return "nullable_{mtype.mangled_cname}"
redef fun is_cprimitive do return false
end
redef class MVirtualType
- redef fun mangled_cname: String do return to_s
+ redef fun mangled_cname do return to_s
end
redef class MGenericType
phase.process_nmodule(nmodule)
if errcount != self.error_count then
self.check_errors
- break
end
errcount = self.error_count
for nclassdef in nmodule.n_classdefs do
end
if errcount != self.error_count then
self.check_errors
- break
end
for na in vannot.annotations do
var p = na.parent
end
if errcount != self.error_count then
self.check_errors
- break
end
end
self.check_errors
while not todo.is_empty do
var mmethoddef = todo.shift
var mmeth = mmethoddef.mproperty
+ var msignature = mmethoddef.msignature
+ if msignature == null then continue # Skip broken method
+
#print "# visit {mmethoddef}"
var v = new RapidTypeVisitor(self, mmethoddef.mclassdef.bound_mtype, mmethoddef)
- var vararg_rank = mmethoddef.msignature.vararg_rank
+ var vararg_rank = msignature.vararg_rank
if vararg_rank > -1 then
var node = self.modelbuilder.mpropdef2node(mmethoddef)
- var elttype = mmethoddef.msignature.mparameters[vararg_rank].mtype
+ var elttype = msignature.mparameters[vararg_rank].mtype
#elttype = elttype.anchor_to(self.mainmodule, v.receiver)
var vararg = self.mainmodule.array_type(elttype)
v.add_type(vararg)
end
# TODO? new_msignature
- var sig = mmethoddef.msignature.as(not null)
+ var sig = msignature
var osig = mmeth.intro.msignature.as(not null)
for i in [0..sig.arity[ do
var origtype = osig.mparameters[i].mtype
continue
else if mmethoddef.constant_value != null then
# Make the return type live
- v.add_type(mmethoddef.msignature.return_mtype.as(MClassType))
+ v.add_type(msignature.return_mtype.as(MClassType))
continue
else if npropdef == null then
abort
if mmethoddef.is_intern or mmethoddef.is_extern then
# UGLY: We force the "instantation" of the concrete return type if any
- var ret = mmethoddef.msignature.return_mtype
+ var ret = msignature.return_mtype
if ret != null and ret isa MClassType and ret.mclass.kind != abstract_kind and ret.mclass.kind != interface_kind then
v.add_type(ret)
end
if not ot.can_resolve_for(t, t, mainmodule) then continue
var rt = ot.anchor_to(mainmodule, t)
if live_types.has(rt) then continue
+ if not check_depth(rt) then continue
#print "{ot}/{t} -> {rt}"
live_types.add(rt)
todo_types.add(rt)
- check_depth(rt)
end
end
#print "MType {live_types.length}: {live_types.join(", ")}"
#print "cast MType {live_cast_types.length}: {live_cast_types.join(", ")}"
end
- private fun check_depth(mtype: MClassType)
+ private fun check_depth(mtype: MClassType): Bool
do
var d = mtype.length
if d > 255 then
self.modelbuilder.toolcontext.fatal_error(null, "Fatal Error: limitation in the rapidtype analysis engine: a type depth of {d} is too important, the problematic type is `{mtype}`.")
+ return false
end
+ return true
end
fun add_new(recv: MClassType, mtype: MClassType)
redef fun visit(n)
do
- n.accept_rapid_type_visitor(self)
if n isa AExpr then
- var implicit_cast_to = n.implicit_cast_to
- if implicit_cast_to != null then self.add_cast_type(implicit_cast_to)
+ if n.mtype != null or n.is_typed then
+ n.accept_rapid_type_visitor(self)
+ var implicit_cast_to = n.implicit_cast_to
+ if implicit_cast_to != null then self.add_cast_type(implicit_cast_to)
+ end
+ else
+ n.accept_rapid_type_visitor(self)
end
# RTA does not enter in AAnnotations
v.set_variable(self, variable, rettype)
- self.is_typed = true
+ self.is_typed = rettype != null
end
end
else
v.visit_expr(nexpr)
v.error(nexpr, "Error: `return` with value in a procedure.")
+ return
end
else if ret_type != null then
v.error(self, "Error: `return` without value in a function.")
+ return
end
self.is_typed = true
end
var mtype = self.attr_type
v.visit_expr_subtype(self.n_value, mtype)
- self.is_typed = true
+ self.is_typed = mtype != null
end
end
var mtype = self.attr_type
if mtype == null then return # Skip error
- self.resolve_reassignment(v, mtype, mtype)
+ var rettype = self.resolve_reassignment(v, mtype, mtype)
- self.is_typed = true
+ self.is_typed = rettype != null
end
end
var nadd = v.builder.make_call(recv, na.push_callsite.as(not null), [self])
place.replace_with(nadd)
end
- super
+
+ visit_all(v)
+
+ if mtype == null and not is_typed then return # Skip broken
+
+ accept_transform_visitor(v)
end
redef fun replace_with(other)
t2 = t2.next #alt2# t2 = null
end
#alt3#t2 = t2.next
+ #alt3#exit(0)
end
if i != null then
bar(i)
else
- break #alt4#
+ break #alt4# exit(0)
end
end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.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.
+
+class Foo
+ fun start do end
+ fun finish do end
+end
+fun foo: Foo do return new Foo
+
+do do
+ 1.output
+end
+while false do do
+ 2.output
+end
+if true then do
+ 3.output
+end else do
+ 4.output
+end
+for i in [0..1] do do
+ 5.output
+end
+with foo do do
+ 6.output
+end
+loop do
+ 7.output
+ return
+end
--- /dev/null
+base_do_block.nit:21,4--23,3: Warning: superfluous `do` block.
+base_do_block.nit:24,16--26,3: Warning: superfluous `do` block.
+base_do_block.nit:32,20--34,3: Warning: superfluous `do` block.
+base_do_block.nit:35,13--37,3: Warning: superfluous `do` block.
+base_do_block.nit:38,6--41,3: Warning: superfluous `do` block.
+1
+3
+5
+5
+6
+7
-alt/base_import_alt3.nit:1,8--21: Error: cannot find module `fail` from `project1`. Tried: ., ../lib/standard, ../lib/standard/collection, alt, ../lib.
+alt/base_import_alt3.nit:1,8--21: Error: cannot find module `fail` from `project1`. Tried: ., ../lib/standard, ../lib/standard/collection, alt, ../lib, ../contrib.
-error_mod_unk.nit:17,8--11: Error: cannot find module `dfgd` from `error_mod_unk`. Tried: ., ../lib/standard, ../lib/standard/collection, alt, ../lib.
+error_mod_unk.nit:17,8--11: Error: cannot find module `dfgd` from `error_mod_unk`. Tried: ., ../lib/standard, ../lib/standard/collection, alt, ../lib, ../contrib.
k
2234
12345.0
+0x12
hello world
--- /dev/null
+test_keep_going.nit:15,11--14: Error: class `Fail` not found in module `test_keep_going`.
-../examples/nitcorn/src/xymus_net.nit:24,8--14: Error: cannot find module `tnitter` from `nitcorn`. Tried: alt, ../lib, ../examples/nitcorn.
-../examples/nitcorn/src/xymus_net.nit:25,8--26: Error: cannot find module `benitlux_controller` from `nitcorn`. Tried: alt, ../lib, ../examples/nitcorn.
-../examples/nitcorn/src/xymus_net.nit:26,8--29: Error: cannot find module `opportunity_controller` from `nitcorn`. Tried: alt, ../lib, ../examples/nitcorn.
+../examples/nitcorn/src/xymus_net.nit:25,8--26: Error: cannot find module `benitlux_controller` from `nitcorn`. Tried: alt, ../lib, ../contrib, ../examples/nitcorn.
+../examples/nitcorn/src/xymus_net.nit:26,8--29: Error: cannot find module `opportunity_controller` from `nitcorn`. Tried: alt, ../lib, ../contrib, ../examples/nitcorn.
# This file is part of NIT ( http://www.nitlanguage.org ).
#
-# Copyright 2011-2013 Alexis Laferrière <alexis.laf@xymus.net>
-#
# 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
# See the License for the specific language governing permissions and
# limitations under the License.
-fun opposite( v : Bool ) : Bool `{
+fun opposite(v: Bool): Bool `{
return v == 0;
`}
-fun plus_10( v : Char ) : Char `{
+
+fun plus_10(v: Char): Char `{
return v + 10;
`}
-fun plus_1000( v : Int ) : Int `{
+
+fun plus_1000(v: Int): Int `{
return v + 1000;
`}
-fun multiply_by_100( v : Float ) : Float `{
+
+fun multiply_by_100(v: Float): Float `{
return v * 100;
`}
-fun print_ns( s : NativeString ) `{
- printf( "%s\n", s );
+
+fun plus_0x10(v: Byte): Byte `{
+ return v + 0x10;
+`}
+
+fun print_ns(s: NativeString) `{
+ printf("%s\n", s);
`}
-print opposite( true )
-print opposite( false )
+print opposite(true)
+print opposite(false)
+
+print plus_10('a')
-print plus_10( 'a' )
+print plus_1000(1234)
-print plus_1000( 1234 )
+print multiply_by_100(123.45)
-print multiply_by_100( 123.45 )
+print plus_0x10(0x2u8)
-print_ns( "hello world".to_cstring )
+print_ns("hello world".to_cstring)
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.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.
+
+fun plop: Fail
+do
+ print 1
+end
+
+1.output
+if false then
+ plop
+end
+2.output
+if false then
+ fail
+end
+3.output
+if false then
+ var x = new Fail
+ x.output
+end
+4.output
+if false then
+ if 1 then abort
+end
+5.output
+if false then
+ abort
+ 999.output
+end
+6.output
+if false then
+ var a = new Sys.fail
+ a.output
+end
+7.output