glViewport(0, 0, display.width, display.height)
glClear gl_COLOR_BUFFER_BIT | gl_DEPTH_BUFFER_BIT
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
return
end
glClear gl_COLOR_BUFFER_BIT | gl_DEPTH_BUFFER_BIT
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
end
# Draw the dynamic screen to the real screen if `dynamic_resolution_ratio != 1.0`
n_floats = 2
glEnableVertexAttribArray dynres_program.tex_coord.location
glVertexAttribPointeri(dynres_program.tex_coord.location, n_floats, gl_FLOAT, false, 0, offset)
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
# Draw
glDrawArrays(gl_TRIANGLE_STRIP, 0, 4)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
# Take down
glBindBuffer(gl_ARRAY_BUFFER, 0)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
sys.perfs["gamnit flat dyn res"].add app.perf_clock_dynamic_resolution.lapse
end
glBindFramebuffer(gl_FRAMEBUFFER, framebuffer)
assert glIsFramebuffer(framebuffer)
self.dynamic_framebuffer = framebuffer
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
# Depth & texture/color
var depthbuffer = glGenRenderbuffers(1).first
self.depth_renderbuffer = depthbuffer
var texture = glGenTextures(1).first
self.texture = texture
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
resize(display, max_dynamic_resolution_ratio)
assert glCheckFramebufferStatus(gl_FRAMEBUFFER) == gl_FRAMEBUFFER_COMPLETE
buffer_array = glGenBuffers(1).first
glBindBuffer(gl_ARRAY_BUFFER, buffer_array)
assert glIsBuffer(buffer_array)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
## coord
var data = new Array[Float]
glBindBuffer(gl_ARRAY_BUFFER, 0)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
end
# Init size or resize `depth_renderbuffer` and `texture`
assert glIsRenderbuffer(depthbuffer)
glRenderbufferStorage(gl_RENDERBUFFER, gl_DEPTH_COMPONENT16, width, height)
glFramebufferRenderbuffer(gl_FRAMEBUFFER, gl_DEPTH_ATTACHMENT, gl_RENDERBUFFER, depthbuffer)
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
# Texture
glBindTexture(gl_TEXTURE_2D, texture)
0, gl_RGB, gl_UNSIGNED_BYTE, new Pointer.nul)
glFramebufferTexture2D(gl_FRAMEBUFFER, gl_COLOR_ATTACHMENT0, gl_TEXTURE_2D, texture, 0)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
# Take down
glBindRenderbuffer(gl_RENDERBUFFER, 0)
glBindFramebuffer(gl_FRAMEBUFFER, 0)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
end
var destroyed = false
# Free the buffer
glDeleteBuffers([buffer_array])
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
buffer_array = -1
# Free the dynamic framebuffer and its attachments
var display = display
assert display != null
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
# Prepare program
var program = simple_2d_program
glViewport(0, 0, display.width, display.height)
glClearColor(0.0, 0.0, 0.0, 1.0)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
# Prepare to draw
for tex in all_root_textures do
redef fun frame_core(display)
do
# Check errors
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
# Update game logic and set sprites
perf_clock_main.lapse
display.flip
# Check errors
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
end
private var frame_dt = 0.0
buffer_array = bufs[0]
buffer_element = bufs[1]
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
end
# Destroy `buffer_array` and `buffer_element`
fun destroy
do
glDeleteBuffers([buffer_array, buffer_element])
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
buffer_array = -1
buffer_element = -1
glBindBuffer(gl_ARRAY_BUFFER, buffer_array)
assert glIsBuffer(buffer_array)
glBufferData(gl_ARRAY_BUFFER, array_bytes, new Pointer.nul, usage)
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
# GL_TRIANGLES 6 vertices * sprite
var n_indices = capacity * indices_per_sprite
glBindBuffer(gl_ELEMENT_ARRAY_BUFFER, buffer_element)
assert glIsBuffer(buffer_element)
glBufferData(gl_ELEMENT_ARRAY_BUFFER, element_bytes, new Pointer.nul, usage)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
buffer_capacity = capacity
glBindBuffer(gl_ELEMENT_ARRAY_BUFFER, buffer_element)
glBufferSubData(gl_ELEMENT_ARRAY_BUFFER, sprite_index*6*2, 6*2, indices.native_array)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
end
# Draw all `sprites`
glBindTexture(gl_TEXTURE_2D, texture.gl_texture)
app.simple_2d_program.texture.uniform 0
end
- var gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
var animation = animation_texture
if animation != null then
glBindTexture(gl_TEXTURE_2D, animation.gl_texture)
app.simple_2d_program.animation_texture.uniform 1
end
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
# Configure attributes, in order:
# vec4 translation, vec4 color, float scale, vec4 coord, vec2 tex_coord, vec4 rotation_row*,
glEnableVertexAttribArray p.translation.location
glVertexAttribPointeri(p.translation.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
size = 4
glEnableVertexAttribArray p.color.location
glVertexAttribPointeri(p.color.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
size = 1
glEnableVertexAttribArray p.scale.location
glVertexAttribPointeri(p.scale.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
size = 4
glEnableVertexAttribArray p.coord.location
glVertexAttribPointeri(p.coord.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
size = 2
glEnableVertexAttribArray p.tex_coord.location
glVertexAttribPointeri(p.tex_coord.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
size = 4
for r in [p.rotation_row0, p.rotation_row1, p.rotation_row2, p.rotation_row3] do
glVertexAttribPointeri(r.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
end
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
end
size = 1
glEnableVertexAttribArray p.animation_fps.location
glVertexAttribPointeri(p.animation_fps.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
size = 1
glEnableVertexAttribArray p.animation_n_frames.location
glVertexAttribPointeri(p.animation_n_frames.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
size = 2
glEnableVertexAttribArray p.animation_coord.location
glVertexAttribPointeri(p.animation_coord.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
size = 2
glEnableVertexAttribArray p.animation_tex_coord.location
glVertexAttribPointeri(p.animation_tex_coord.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
size = 2
glEnableVertexAttribArray p.animation_tex_diff.location
glVertexAttribPointeri(p.animation_tex_diff.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
size = 1
glEnableVertexAttribArray p.animation_start.location
glVertexAttribPointeri(p.animation_start.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
size = 1
glEnableVertexAttribArray p.animation_loops.location
glVertexAttribPointeri(p.animation_loops.location, size, gl_FLOAT, false, bytes_per_vertex, offset)
offset += size * sizeof_gl_float
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
# Actual draw
for s in sprites.starts, e in sprites.ends do
var l = e-s
glDrawElementsi(gl_TRIANGLES, l*indices_per_sprite, gl_UNSIGNED_SHORT, 2*s*indices_per_sprite)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
end
# Take down
p.rotation_row0, p.rotation_row1, p.rotation_row2, p.rotation_row3: Attribute] do
if not attr.is_active then continue
glDisableVertexAttribArray(attr.location)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
end
glBindBuffer(gl_ARRAY_BUFFER, 0)
glBindBuffer(gl_ELEMENT_ARRAY_BUFFER, 0)
- gl_error = glGetError
- assert gl_error == gl_NO_ERROR else print_error gl_error
+ assert glGetError == gl_NO_ERROR
end
end
# General factory to build semantic nodes in the AST of expressions
class ASTBuilder
# The module used as reference for the building
- # It is used to gather types and other stufs
+ # It is used to gather types and other stuff
var mmodule: MModule
# The anchor used for some mechanism relying on types
return new AIntegerExpr.make(value, mmodule.int_type)
end
- # Make a new instatiation
+ # Make a new instantiation
fun make_new(callsite: CallSite, args: nullable Array[AExpr]): ANewExpr
do
return new ANewExpr.make(callsite, args)
return new ABreakExpr.make(escapemark)
end
- # Make a new condinionnal
+ # Make a new conditional
# `mtype` is the return type of the whole if, in case of a ternary operator.
fun make_if(condition: AExpr, mtype: nullable MType): AIfExpr
do
private var variable_cache: nullable Variable
# The `detach` method completely remove the node in the parent.
- # Owever, sometime, it is useful to keep the emplacement of the removed child.
+ # However, sometime, it is useful to keep the emplacement of the removed child.
#
- # The standard usecase is the insertion of a node beetwen a parent `p` and a child `p.c`.
+ # The standard use case is the insertion of a node between a parent `p` and a child `p.c`.
# To create the new node `n`, we need to attach the child to it.
# But, to put `n` where `c` was in `p`, the place has to be remembered.
#
end
# A placeholder for a `AExpr` node
-# Instances are transiantly used to mark some specific emplacments in the AST
+# Instances are transiantly used to mark some specific emplacements in the AST
# during complex transformations.
#
# Their must not appear in a valid AST
self.is_typed = true
end
- redef fun add(expr: AExpr)
+ redef fun add(expr)
do
n_expr.add expr
end
n_block.is_typed = true
end
- redef fun add(expr: AExpr)
+ redef fun add(expr)
do
n_block.add expr
end
return new ABreakExpr.make(escapemark)
end
- redef fun add(expr: AExpr)
+ redef fun add(expr)
do
n_block.add expr
end
import mixin
import counter
import pkgconfig
+private import explain_assert_api
# Add compiling options
redef class ToolContext
var cond = v.expr_bool(self.n_expr)
v.add("if (unlikely(!{cond})) \{")
v.stmt(self.n_else)
+
+ explain_assert v
+
var nid = self.n_id
if nid != null then
v.add_abort("Assert '{nid.text}' failed")
end
v.add("\}")
end
+
+ # Explain assert if it fails
+ private fun explain_assert(v: AbstractCompilerVisitor)
+ do
+ var explain_assert_str = explain_assert_str
+ if explain_assert_str == null then return
+
+ var nas = v.compiler.modelbuilder.model.get_mclasses_by_name("NativeArray")
+ if nas == null then return
+
+ var expr = explain_assert_str.expr(v)
+ if expr == null then return
+
+ var cstr = v.send(v.get_property("to_cstring", expr.mtype), [expr])
+ if cstr == null then return
+
+ v.add "PRINT_ERROR(\"Runtime assert: %s\\n\", {cstr});"
+ end
end
redef class AOrExpr
import frontend
import actors_generation_phase
import serialization_code_gen_phase
+import explain_assert
--- /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.
+
+# Explain failed assert to the console by modifying the AST.
+#
+# This module implements the service `AAssertExpr::explain_assert_str`,
+# which should be used by the engines.
+#
+# Example assert:
+#
+# ~~~nitish
+# var x = 0.0
+# var y = 1.0
+# assert x.is_approx(y, 0.5)
+# ~~~
+#
+# Produces the following output on failure:
+#
+# ~~~raw
+# Runtime assert: 0.0.is_approx(1.0, 0.5)
+# ~~~
+module explain_assert
+
+import astbuilder
+intrude import literal # for value=
+intrude import typing # for mtype=
+import astvalidation
+
+import explain_assert_api
+
+redef class ToolContext
+
+ # Phase modifying the AST to explain assets when they fail
+ var explain_assert_phase: Phase = new ExplainAssertPhase(self, [modelize_class_phase, typing_phase, literal_phase])
+end
+
+private class ExplainAssertPhase
+ super Phase
+
+ redef fun process_nmodule(nmodule)
+ do
+ var mmodule = nmodule.mmodule
+ if mmodule == null then return
+
+ # Skip if `mmodule` doesn't have access to `String`
+ var string_class = toolcontext.modelbuilder.try_get_mclass_by_name(nmodule, mmodule, "String")
+ if string_class == null then return
+
+ # Launch a visitor on all elements of the AST
+ var visitor = new ExplainAssertVisitor(toolcontext, mmodule, string_class.mclass_type)
+ visitor.enter_visit nmodule
+ end
+end
+
+# Visitor to find and explain asserts
+private class ExplainAssertVisitor
+ super Visitor
+
+ # The toolcontext is our entry point to most services
+ var toolcontext: ToolContext
+
+ # The visited module
+ var mmodule: MModule
+
+ # Type of `String` (the generated code does not work without a `String`)
+ var string_mtype: MType
+
+ # Tool to modify the AST
+ var builder = new ASTBuilder(mmodule) is lazy
+
+ redef fun visit(node)
+ do
+ # Recursively visit all sub-nodes
+ node.visit_all(self)
+
+ # Only work on asserts
+ if not node isa AAssertExpr then return
+ var expr = node.n_expr
+
+ # Skip assert on a single boolean var and asserts on false:
+ # ~~~
+ # assert false
+ # # or
+ # var x = false # Or any boolean expression
+ # assert x
+ # ~~~
+ if expr isa AVarExpr or expr isa AFalseExpr then return
+
+ # Build the superstring to explain the assert
+ var explain_str = new ASuperstringExpr
+
+ # Prepare attribute used by visited nodes
+ self.assert_node = node
+ self.explain_str = explain_str
+ expr.accept_explain_assert self
+
+ # Done! Store the superstring in the assert's node
+ if explain_str.n_exprs.not_empty then
+ node.explain_assert_str = explain_str
+ end
+ end
+
+ # Visited assert node
+ var assert_node: AAssertExpr is noinit
+
+ # Superstring in construction to explain the `assert_node`
+ var explain_str: ASuperstringExpr is noinit
+
+ # Build an `AStringExpr` containing `value`
+ #
+ # Add it to `explain_str` if `auto_add == true`, the default.
+ fun explain_string(value: String, auto_add: nullable Bool): AStringExpr
+ do
+ auto_add = auto_add or else true
+
+ var tk = new TString
+ tk.text = "\"{value}\""
+ var op = new AStringExpr
+ op.n_string = tk
+ op.mtype = string_mtype
+ op.value = value
+ op.location = assert_node.location
+
+ if auto_add then explain_str.n_exprs.add op
+ return op
+ end
+
+ # Add the value of `v_expr` to `explain_str` and protect null values
+ fun explain_expr(v_expr: AExpr)
+ do
+ var mtype = v_expr.mtype
+ if mtype == null then
+ explain_string "<unexpected error>"
+ return
+ end
+
+ # Set the expression value aside
+ var old_parent = v_expr.parent
+ var expr = v_expr.make_var_read
+ if old_parent != null then old_parent.validate
+
+ # Protect nullable types
+ if mtype isa MNullType then
+ explain_string "null"
+ return
+ else if mtype isa MNullableType then
+ var e = new AOrElseExpr
+ e.n_expr = expr
+ e.n_expr2 = explain_string("null", false)
+ e.location = assert_node.location
+ e.mtype = mmodule.object_type
+
+ explain_str.n_exprs.add e
+ return
+ end
+
+ explain_str.n_exprs.add expr
+ end
+
+ # Add all the arguments in `AExprs` to `explain_str`
+ fun explain_args(n_args: AExprs)
+ do
+ var first = true
+ for n_arg in n_args.to_a do
+ if not first then
+ explain_string ", "
+ else first = false
+
+ explain_expr n_arg
+ end
+ end
+end
+
+redef class AAssertExpr
+ redef var explain_assert_str = null
+end
+
+redef class AExpr
+ # Fill `v` to explain this node if the parent assert fails
+ private fun accept_explain_assert(v: ExplainAssertVisitor)
+ do if mtype != null then v.explain_expr self
+end
+
+redef class ABinopExpr
+ redef fun accept_explain_assert(v)
+ do
+ if n_expr.mtype == null or n_expr2.mtype == null then return
+
+ v.explain_expr n_expr
+ v.explain_string " {n_op.text} "
+ v.explain_expr n_expr2
+ end
+end
+
+redef class ACallExpr
+ redef fun accept_explain_assert(v)
+ do
+ if n_expr.mtype == null then return
+
+ v.explain_expr n_expr
+ v.explain_string ".{n_qid.n_id.text}"
+
+ if n_args.to_a.not_empty then
+ v.explain_string "("
+ v.explain_args n_args
+ v.explain_string ")"
+ end
+ end
+end
+
+redef class ABraExpr
+ redef fun accept_explain_assert(v)
+ do
+ if n_expr.mtype == null then return
+
+ v.explain_expr n_expr
+ v.explain_string "["
+ v.explain_args n_args
+ v.explain_string "]"
+ end
+end
+
+redef class AIsaExpr
+ redef fun accept_explain_assert(v)
+ do
+ if n_expr.mtype == null then return
+
+ v.explain_expr n_expr
+ v.explain_string " {n_kwisa.text} "
+ v.explain_string n_type.collect_text
+ end
+end
+
+redef class ANotExpr
+ redef fun accept_explain_assert(v)
+ do
+ v.explain_string "{n_kwnot.text} "
+ n_expr.accept_explain_assert v
+ end
+end
+
+redef class ABinBoolExpr
+ # Don't explain the conditions using `and`, `or`, etc.
+ redef fun accept_explain_assert(v) do 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.
+
+# Explain failed assert to the console (service declaration only)
+#
+# The only service `assert_expr_str` is implemented by the
+# `explain_assert` module.
+module explain_assert_api
+
+import parser
+
+redef class AAssertExpr
+ # Superstring explaining `self` if the assert fails
+ #
+ # Engines should print out this superstring.
+ fun explain_assert_str: nullable ASuperstringExpr do return null
+end
import mixin
import primitive_types
private import model::serialize_model
+private import frontend::explain_assert_api
redef class ToolContext
# --discover-call-trace
if not cond.is_true then
v.stmt(self.n_else)
if v.is_escaping then return
+
+ # Explain assert if it fails
+ var explain_assert_str = explain_assert_str
+ if explain_assert_str != null then
+ var i = v.expr(explain_assert_str)
+ if i isa MutableInstance then
+ var res = v.send(v.force_get_primitive_method("to_cstring", i.mtype), [i])
+ if res != null then
+ var val = res.val
+ if val != null then
+ print_error "Runtime assert: {val.to_s}"
+ end
+ end
+ end
+ end
+
var nid = self.n_id
if nid != null then
fatal(v, "Assert '{nid.text}' failed")
test_rubix_cube
test_csv
repeating_key_xor_solve
+test_explain_assert
+base_notnull_lit_alt2
+assertions
+Runtime assert: 5 == 42
Runtime error: Assert failed (../examples/rosettacode/assertions.nit:11)
+Runtime assert: 5 == null
Runtime error: Assert failed (alt/base_notnull_lit_alt2.nit:19)
Before Test
Tested method
After Test
+ Runtime assert: <TestTestSuite>.before
Runtime error: Assert failed (test_nitunit4/test_nitunit4_base.nit:28)
[OK] test_nitunit4$TestTestSuite$test_bar
After Test
-Docunits: Entities: 21; Documented ones: 0; With nitunits: 0
+Docunits: Entities: 22; Documented ones: 0; With nitunits: 0
Test suites: Classes: 3; Test Cases: 8; Failures: 7
[FAILURE] 7/8 tests failed.
`nitunit.out` is not removed for investigation.
</failure></testcase></testsuite><testsuite package="test_nitunit4::test_nitunit4"></testsuite><testsuite package="test_nitunit4"><testcase classname="nitunit.test_nitunit4.TestTestSuite" name="test_foo" time="0.0"><error message="Runtime Error in file nitunit.out/gen_test_nitunit4.nit">Before Test
Tested method
After Test
+Runtime assert: <TestTestSuite>.before
Runtime error: Assert failed (test_nitunit4/test_nitunit4_base.nit:28)
</error></testcase><testcase classname="nitunit.test_nitunit4.TestTestSuite" name="test_bar" time="0.0"><system-err>Before Test
Tested method
+++ /dev/null
-Runtime error: Assert failed (../lib/c.nit:37)
-0
-0
-1
-2
-3
-4
-[0,1,2,3,4]
--- /dev/null
+Runtime assert: 1 == some string
+Runtime error: Assert failed (alt/test_explain_assert_alt1.nit:27)
--- /dev/null
+Runtime error: Assert failed (alt/test_explain_assert_alt10.nit:46)
+foo
--- /dev/null
+Runtime assert: not 1 == 1
+Runtime error: Assert failed (alt/test_explain_assert_alt11.nit:48)
--- /dev/null
+Runtime assert: 4 isa MyClass
+Runtime error: Assert failed (alt/test_explain_assert_alt12.nit:49)
--- /dev/null
+Runtime error: Assert failed (alt/test_explain_assert_alt13.nit:52)
--- /dev/null
+alt/test_explain_assert_alt2.nit:28,8: Warning: expression is not null, since it is a `Int`.
+Runtime assert: 1 == null
+Runtime error: Assert failed (alt/test_explain_assert_alt2.nit:28)
--- /dev/null
+Runtime assert: 12 == null
+Runtime error: Assert failed (alt/test_explain_assert_alt3.nit:29)
+foo
--- /dev/null
+Runtime assert: null != null
+Runtime error: Assert failed (alt/test_explain_assert_alt4.nit:30)
+foo
--- /dev/null
+Runtime assert: 0.0.is_approx(1.0, 0.5)
+Runtime error: Assert failed (alt/test_explain_assert_alt5.nit:34)
--- /dev/null
+Runtime assert: not true
+Runtime error: Assert failed (alt/test_explain_assert_alt6.nit:36)
--- /dev/null
+Runtime assert: [true,false,true][1]
+Runtime error: Assert failed (alt/test_explain_assert_alt7.nit:39)
--- /dev/null
+Runtime assert: [0,1,2].is_empty
+Runtime error: Assert failed (alt/test_explain_assert_alt8.nit:41)
--- /dev/null
+Runtime assert: <MyClass i:12 s:asdf> == 0
+Runtime error: Assert failed (alt/test_explain_assert_alt9.nit:43)
print ci.to_a
ci.destroy
-#alt4#print ci[0]
+assert ci.destroyed
--- /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 MyClass
+ var i = 12
+ var s = "asdf"
+ redef fun to_s do return "<{class_name} i:{i} s:{s}>"
+end
+
+fun foo(v: nullable Int): nullable Int do
+ print "foo"
+ return v
+end
+
+assert 1 == 1
+#alt1#assert 1 == "some string"
+#alt2#assert 1 == null
+#alt3#assert foo(12) == null
+#alt4#assert foo(null) != null
+
+#alt5#var x = 0.0
+#alt5#var y = 1.0
+#alt5#assert x.is_approx(y, 0.5)
+
+#alt6#assert not true
+
+#alt7#var a = [true, false, true]
+#alt7#assert a[1]
+
+#alt8#assert [0, 1, 2].is_empty
+
+#alt9#assert (new MyClass) == 0
+
+#alt10#var n = foo(null)
+#alt10#assert n != null and n.to_s == "crash" # Not explained
+
+#alt11#assert not 1 == 1
+#alt12#assert 4 isa MyClass
+
+#alt13#var f = false
+#alt13#assert f # Not explained
fun test_sav_conflict is test do
print "Tested method"
end
+
+ redef fun to_s do return "<{class_name}>"
end