module java_compiler
import rapid_type_analysis
+import transform
import frontend
redef class ToolContext
# Where to output tmp files
var opt_compile_dir = new OptionString("Directory used to generate temporary files", "--compile-dir")
+ # Compile using ant instead of make (faster, but no error display)
+ var opt_ant = new OptionBool("Batch with ant (faster, but no error display)", "--ant")
+
redef init do
super
- option_context.add_option(opt_output, opt_compile_dir)
+ option_context.add_option(opt_output, opt_compile_dir, opt_ant)
end
end
time0 = time1
toolcontext.info("*** COMPILING JAVA ***", 1)
- build_with_make(compiler, jfiles)
+ if toolcontext.opt_ant.value then
+ build_with_ant(compiler, jfiles)
+ else
+ build_with_make(compiler, jfiles)
+ end
write_shell_script(compiler)
time1 = get_time
fun write_java_files(compiler: JavaCompiler): Array[String] do
var jfiles = new Array[String]
for f in compiler.files do
- var file = new FileWriter.open("{compiler.compile_dir}/{f.filename}")
+ var filepath = "{compiler.compile_dir}/{f.filename}"
+ var file = cache_file(filepath)
for line in f.lines do file.write(line)
- file.close
+ close_cache(filepath, file)
jfiles.add(f.filename)
end
return jfiles
end
+ # Cache a file as `{filepath}.tmp` and replace the original if different
+ private fun cache_file(filepath: String): FileWriter do
+ if toolcontext.opt_ant.value and filepath.file_exists then
+ return new FileWriter.open("{filepath}.tmp")
+ else
+ return new FileWriter.open(filepath)
+ end
+ end
+
+ # Close the writer and move tmp file to original if modified
+ private fun close_cache(filepath: String, file: FileWriter) do
+ file.close
+ if "{filepath}.tmp".file_exists then
+ sys.system("if ! diff {filepath}.tmp {filepath} > /dev/null; then mv {filepath}.tmp {filepath}; else rm {filepath}.tmp; fi")
+ end
+ end
+
# Compile Java generated files using `make`
fun build_with_make(compiler: JavaCompiler, jfiles: Array[String]) do
write_manifest(compiler)
if res != 0 then toolcontext.error(null, "make failed! Error code: {res}.")
end
+ # Compile Java sources using `ant`
+ fun build_with_ant(compiler: JavaCompiler, jfiles: Array[String]) do
+ compile_antfile(compiler, jfiles)
+ var outname = compiler.outname.to_path.filename
+ var antpath = "{compiler.compile_dir}/{outname}.xml"
+ self.toolcontext.info("ant jar -f {antpath}", 2)
+ var res
+ if self.toolcontext.verbose_level >= 3 then
+ res = sys.system("ant jar -f {antpath} 2>&1")
+ else
+ res = sys.system("ant jar -f {antpath} 2>&1 > /dev/null")
+ end
+ if res != 0 then
+ toolcontext.error(null, "ant compile failed! Error code: {res}.")
+ end
+ end
+
# Write the Makefile used to compile Java generated files into an executable jar
fun write_makefile(compiler: JavaCompiler, jfiles: Array[String]) do
# list class files from jfiles
toolcontext.info("Generated makefile: {makename}", 2)
end
+ # The Ant `build.xml` script used to compile build the final jar
+ fun compile_antfile(compiler: JavaCompiler, jfiles: Array[String]) do
+ var compile_dir = compiler.compile_dir
+ var outname = compiler.outname.to_path.filename
+ var outpath = (sys.getcwd / compiler.outname).simplify_path
+ var antname = "{compile_dir}/{outname}.xml"
+ var antfile = new FileWriter.open(antname)
+ var jname = compiler.mainmodule.jname
+ antfile.write("<project>")
+ antfile.write(" <target name=\"compile\">")
+ antfile.write(" <mkdir dir=\"classes\"/>")
+ antfile.write(" <javac includes=\"{compiler.mainmodule.jname}_Main.java {jfiles.join(" ")}\" srcdir=\".\" destdir=\"classes\"/>")
+ antfile.write(" </target>")
+ antfile.write(" <target name=\"jar\" depends=\"compile\">")
+ antfile.write(" <jar destfile=\"{outpath}.jar\" basedir=\"classes\">")
+ antfile.write(" <manifest>")
+ antfile.write(" <attribute name=\"Main-Class\" value=\"{jname}_Main\"/>")
+ antfile.write(" </manifest>")
+ antfile.write(" </jar>")
+ antfile.write(" </target>")
+ antfile.write("</project>")
+ antfile.close
+ toolcontext.info("Generated antfile: {antname}", 2)
+ end
+
# Write the Java manifest file
private fun write_manifest(compiler: JavaCompiler) do
var compile_dir = compiler.compile_dir
# compile method structures
compile_mmethods_to_java
- # TODO compile main
- modelbuilder.toolcontext.info("NOT YET IMPLEMENTED", 0)
+ # compile main
+ compile_main_function
end
# Prepare the boxes used to represent Java primitive types
end
end
end
+
+ # Generate Java main that call Sys.main
+ fun compile_main_function do
+ var v = new_visitor("{mainmodule.jname}_Main.java")
+ v.add("public class {mainmodule.jname}_Main \{")
+ v.add(" public static void main(String[] args) \{")
+
+ var main_type = mainmodule.sys_type
+ if main_type != null then
+ var mainmodule = v.compiler.mainmodule
+ var glob_sys = v.init_instance(main_type)
+ var main_init = mainmodule.try_get_primitive_method("init", main_type.mclass)
+ if main_init != null then
+ v.send(main_init, [glob_sys])
+ end
+ var main_method = mainmodule.try_get_primitive_method("run", main_type.mclass) or else
+ mainmodule.try_get_primitive_method("main", main_type.mclass)
+ if main_method != null then
+ v.send(main_method, [glob_sys])
+ end
+ end
+ v.add(" \}")
+ v.add("\}")
+ end
end
# The class visiting the AST
end
end
+ # Return an unique and stable identifier associated with an escapemark
+ fun escapemark_name(e: nullable EscapeMark): String do
+ assert e != null
+ var frame = self.frame
+ assert frame != null
+ if frame.escapemark_names.has_key(e) then return frame.escapemark_names[e]
+ var name = e.name
+ if name == null then name = "label"
+ name = get_name(name)
+ frame.escapemark_names[e] = name
+ return name
+ end
+
+ # Insert a C label for associated with an escapemark
+ fun add_escape_label(e: nullable EscapeMark) do
+ if e == null then return
+ if e.escapes.is_empty then return
+ add("BREAK_{escapemark_name(e)}: ")
+ end
+
# Variables handling
# Registered variables
res.add(null_instance)
continue
end
- if param.is_vararg and map.vararg_decl > 0 then
- var vararg = exprs.sub(j, map.vararg_decl)
+ if param.is_vararg and args[i].vararg_decl > 0 then
+ var vararg = exprs.sub(j, args[i].vararg_decl)
var elttype = param.mtype
var arg = self.vararg_instance(mpropdef, recv, vararg, elttype)
res.add(arg)
return res
end
+ # Generate a super call from a method definition
+ fun supercall(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable do
+ return table_send(m, args)
+ end
+
# Generate a monomorphic send for the method `m`, the type `t` and the arguments `args`
fun monomorphic_send(m: MMethod, t: MType, args: Array[RuntimeVariable]): nullable RuntimeVariable do
assert t isa MClassType
# Compile a statement (if any)
fun stmt(nexpr: nullable AExpr) do
if nexpr == null then return
+ if nexpr.mtype == null and not nexpr.is_typed then
+ # Untyped expression.
+ # Might mean dead code or invalid code
+ # so aborts
+ add_abort("FATAL: bad statement executed.")
+ return
+ end
+
var old = self.current_node
current_node = nexpr
nexpr.stmt(self)
res = nexpr.expr(self)
end
+ if res == null then
+ # Untyped expression.
+ # 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
+ res = null_instance
+
+ self.current_node = old
+ return res
+ end
+
if mtype != null then
mtype = anchor(mtype)
res = autobox(res, mtype)
return res
end
+ # Alias for `self.expr(nexpr, self.bool_type)`
+ fun expr_bool(nexpr: AExpr): RuntimeVariable do
+ return expr(nexpr, compiler.mainmodule.bool_type)
+ end
+
# Correctly assign a left and a right value
# Boxing and unboxing is performed if required
fun assign(left, right: RuntimeVariable) do
# Used by aborts, asserts, casts, etc.
fun add_abort(message: String) do
add("System.err.print(\"Runtime error: {message}\");")
+ add_raw_abort
+ end
+
+ # Abort without displaying the cause.
+ #
+ # Used to customizable errors.
+ private fun add_raw_abort do
var node = current_node
if node != null then
add("System.err.print(\" ({node.location.short_location})\");")
add("System.exit(1);")
end
+ # Add a dynamic cast
+ fun add_cast(value: RuntimeVariable, mtype: MType) do
+ var res = type_test(value, mtype)
+ add("if (!{res}) \{")
+ add("System.err.print(\"Runtime error: Cast failed. Expected `{mtype.to_s.escape_to_c}`, got `\" + {value}.rtclass.class_name + \"`\");")
+ add_raw_abort
+ add("\}")
+ end
+
# Types handling
# Anchor a type to the main module and the current receiver
return k == interface_kind or t.is_java_primitive
end
+ # Generate a polymorphic subtype test
+ fun type_test(value: RuntimeVariable, mtype: MType): RuntimeVariable do
+ add("/* {value.inspect} isa {mtype} */")
+ var res = self.new_var(compiler.mainmodule.bool_type)
+
+ # check color is in table
+ var maybenull = (value.mcasttype isa MNullableType or value.mcasttype isa MNullType)
+ if maybenull then
+ add("if({value} == null || {value}.is_null()) \{")
+ add("{res} = true && {mtype isa MNullableType};")
+ add("\} else \{")
+ end
+ if mtype isa MNullableType then mtype = mtype.mtype
+ var mclass = mtype.as(MClassType).mclass
+ add("{res} = {value}.rtclass.supers.get(\"{mclass.jname}\") == {mclass.rt_name}.get{mclass.rt_name}();")
+ if maybenull then
+ add("\}")
+ end
+ return res
+ end
+
+ # Generate the code required to dynamically check if 2 objects share the same runtime type
+ fun is_same_type_test(value1, value2: RuntimeVariable): RuntimeVariable do
+ var res = self.new_var(compiler.mainmodule.bool_type)
+ add("{res} = {value1}.rtclass == {value2}.rtclass;")
+ return res
+ end
+
# Native instances
# Generate an integer value
# Attributes
+ # Generate a polymorphic attribute is_set test
+ fun isset_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable do
+ # TODO self.check_recv_notnull(recv)
+ var res = new_var(compiler.mainmodule.bool_type)
+
+ # What is the declared type of the attribute?
+ var mtype = a.intro.static_mtype.as(not null)
+ var intromclassdef = a.intro.mclassdef
+ mtype = mtype.resolve_for(intromclassdef.bound_mtype, intromclassdef.bound_mtype, intromclassdef.mmodule, true)
+
+ if mtype isa MNullableType then
+ add("{res} = true; /* easy isset: {a} on {recv.inspect} */")
+ return res
+ end
+ add("{res} = {recv}.attrs.get(\"{a.jname}\") != null; /* {a} on {recv.inspect} */")
+ return res
+ end
+
# Generate a polymorphic attribute read
fun read_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable do
# TODO check_recv_notnull(recv)
var intromclassdef = a.intro.mclassdef
ret = ret.resolve_for(intromclassdef.bound_mtype, intromclassdef.bound_mtype, intromclassdef.mmodule, true)
+ # Check for Uninitialized attribute
+ if not ret isa MNullableType then check_attribute(a, recv)
+
return new_expr("{recv}.attrs.get(\"{a.jname}\")", ret)
end
add "{recv}.attrs.put(\"{a.jname}\", {autobox(value, compiler.mainmodule.object_type)});"
end
+ # Check uninitialized attribute
+ fun check_attribute(a: MAttribute, recv: RuntimeVariable) do
+ add "if({recv}.attrs.get(\"{a.jname}\") == null) \{"
+ add_abort "Uninitialized attribute {a.name}"
+ add "\}"
+ end
+
# Utils
# Display a info message
# The label at the end of the property
var returnlabel: nullable String = null is writable
+
+ # Labels associated to a each escapemarks.
+ # Because of inlinings, escape-marks must be associated to their context (the frame)
+ private var escapemark_names = new HashMap[EscapeMark, String]
end
redef class Location
redef class MClass
# Runtime name
- private fun rt_name: String do return "RTClass_{intro.mmodule.jname}_{jname}"
+ private fun rt_name: String do return "RTClass_{intro_mmodule.jname}_{jname}"
# Generate a Java RTClass for a Nit MClass
fun compile_to_java(v: JavaCompilerVisitor) do
var modelbuilder = v.compiler.modelbuilder
var node = modelbuilder.mpropdef2node(self)
+ var recv = mclassdef.bound_mtype
+ var arguments = new Array[RuntimeVariable]
+ var frame = new JavaStaticFrame(v, self, recv, arguments)
+ v.frame = frame
+
+ var selfvar = v.decl_var("self", recv)
+ arguments.add(selfvar)
+ var boxed = v.new_expr("args[0]", v.compiler.mainmodule.object_type)
+ v.add "{selfvar} = {v.autobox(boxed, recv)};"
+
+ var msignature = self.msignature
+ var ret = null
+ if msignature != null then
+ ret = msignature.return_mtype
+ if ret != null then
+ var retvar = v.decl_var("ret", ret)
+ if ret.name == "Int" then v.add "{retvar} = 0;"
+ if ret.name == "Float" then v.add "{retvar} = 0.0;"
+ if ret.name == "Bool" then v.add "{retvar} = false;"
+ if ret.name == "Char" then v.add "{retvar} = 0;"
+ if ret.name == "Byte" then v.add "{retvar} = 0;"
+ frame.returnvar = retvar
+ end
+ end
+ frame.returnlabel = v.get_name("RET_LABEL")
+
+ v.current_node = node
if is_abstract then
v.add_abort("Abstract method `{mproperty.name}` called on `\" + {selfvar}.rtclass.class_name +\"`")
v.add("return null;")
return
end
+ v.current_node = null
+
+ v.add("{frame.returnlabel.as(not null)}: \{")
if node isa APropdef then
- node.compile_to_java(v, self)
+ node.compile_to_java(v, self, arguments)
else if node isa AClassdef then
- node.compile_to_java(v, self)
+ node.compile_to_java(v, self, arguments)
else
abort
end
+
+ v.add("\}")
+ if ret != null then
+ v.add("return {v.autobox(frame.returnvar.as(not null), v.compiler.mainmodule.object_type)};")
+ else
+ v.add("return null;")
+ end
end
end
redef class AClassdef
- private fun compile_to_java(v: JavaCompilerVisitor, mpropdef: MMethodDef) do
- if mpropdef == self.mfree_init then
- assert mpropdef.mproperty.is_root_init
+ private fun compile_to_java(v: JavaCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]) do
+ if mpropdef.mproperty.is_root_init then
if not mpropdef.is_intro then
- # TODO v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
+ v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
end
else
abort
end
- v.add("return null;")
end
end
redef class APropdef
# Compile that property definition to java code
- fun compile_to_java(v: JavaCompilerVisitor, mpropdef: MMethodDef) do
+ fun compile_to_java(v: JavaCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]) do
v.info("NOT YET IMPLEMENTED {class_name}::compile_to_java")
- v.add("return null;")
end
end
redef class AMethPropdef
- redef fun compile_to_java(v, mpropdef) do
- # TODO Call the implicit super-init
-
- var recv = mpropdef.mclassdef.bound_mtype
- var arguments = new Array[RuntimeVariable]
- var frame = new JavaStaticFrame(v, mpropdef, recv, arguments)
- v.frame = frame
-
- var selfvar = v.decl_var("self", recv)
- arguments.add(selfvar)
- var boxed = v.new_expr("args[0];", v.compiler.mainmodule.object_type)
- v.add "{selfvar} = {v.unbox(boxed, recv)};"
-
- var msignature = mpropdef.msignature
- var ret = null
- if msignature != null then
- ret = msignature.return_mtype
- if ret != null then frame.returnvar = v.new_var(ret)
- end
- frame.returnlabel = v.get_name("RET_LABEL")
-
- if not mpropdef.is_intern and msignature != null then
+ redef fun compile_to_java(v, mpropdef, arguments) do
+ if mpropdef.msignature != null then
var i = 0
- for mparam in msignature.mparameters do
+ for mparam in mpropdef.msignature.as(not null).mparameters do
var variable = n_signature.as(not null).n_params[i].variable
if variable == null then continue
var argvar = v.variable(variable)
- boxed = v.new_expr("args[{i + 1}];", v.compiler.mainmodule.object_type)
- v.add "{argvar} = {v.unbox(boxed, mparam.mtype)};"
+ v.assign(argvar, v.new_expr("args[{i + 1}]", v.compiler.mainmodule.object_type))
arguments.add(argvar)
i += 1
end
end
- v.add("{frame.returnlabel.as(not null)}: \{")
- compile_inside_to_java(v, mpropdef)
- v.add("\}")
-
- if ret != null then
- if ret.is_java_primitive then
- boxed = v.box(frame.returnvar.as(not null), v.compiler.mainmodule.object_type)
- v.add("return {boxed};")
- else
- v.add("return {frame.returnvar.as(not null)};")
+ # Call the implicit super-init
+ var auto_super_inits = self.auto_super_inits
+ if auto_super_inits != null then
+ var args = [arguments.first]
+ for auto_super_init in auto_super_inits do
+ assert auto_super_init.mproperty != mpropdef.mproperty
+ args.clear
+ for i in [0..auto_super_init.msignature.arity+1[ do
+ args.add(arguments[i])
+ end
+ assert auto_super_init.mproperty != mpropdef.mproperty
+ v.compile_callsite(auto_super_init, args)
end
- else
- v.add("return null;")
end
- v.frame = null
+ if auto_super_call then
+ v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
+ end
+
+ compile_inside_to_java(v, mpropdef, arguments)
end
# Compile the inside of the method body
- private fun compile_inside_to_java(v: JavaCompilerVisitor, mpropdef: MMethodDef) do
+ private fun compile_inside_to_java(v: JavaCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]) do
# Compile intern methods
if mpropdef.is_intern then
if compile_intern_to_java(v, mpropdef, arguments) then return
else if pname == "%" then
v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
return true
- else if pname == "lshift" then
+ else if pname == "<<" then
v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
return true
- else if pname == "rshift" then
+ else if pname == ">>" then
v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
return true
else if pname == "==" then
else if pname == "%" then
v.ret(v.new_expr("(byte)({arguments[0]} % {arguments[1]})", ret.as(not null)))
return true
- else if pname == "lshift" then
+ else if pname == "<<" then
v.ret(v.new_expr("(byte)({arguments[0]} << {arguments[1]})", ret.as(not null)))
return true
- else if pname == "rshift" then
+ else if pname == ">>" then
v.ret(v.new_expr("(byte)({arguments[0]} >> {arguments[1]})", ret.as(not null)))
return true
else if pname == "==" then
value = v.new_var(mtype)
frame.returnvar = value
frame.returnlabel = v.get_name("RET_LABEL")
- v.add("\{")
+ v.add("{frame.returnlabel.as(not null)}: \{")
v.stmt(nblock)
- v.add("{frame.returnlabel.as(not null)}:(void)0;")
v.add("\}")
else
abort
end
end
+redef class ASuperExpr
+ redef fun expr(v)
+ do
+ var frame = v.frame
+ assert frame != null
+ var recv = frame.arguments.first
+
+ var callsite = self.callsite
+ if callsite != null then
+ var args
+
+ if self.n_args.n_exprs.is_empty then
+ # Add automatic arguments for the super init call
+ args = [recv]
+ for i in [0..callsite.msignature.arity[ do
+ args.add(frame.arguments[i+1])
+ end
+ else
+ args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
+ end
+
+ # Super init call
+ var res = v.compile_callsite(callsite, args)
+ return res
+ end
+
+ var mpropdef = self.mpropdef.as(not null)
+
+ var args
+ if self.n_args.n_exprs.is_empty then
+ args = frame.arguments
+ else
+ args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
+ end
+
+ # Standard call-next-method
+ return v.supercall(mpropdef, recv.mtype.as(MClassType), args)
+ end
+end
+
redef class ASelfExpr
redef fun expr(v) do return v.frame.as(not null).arguments.first
end
redef fun expr(v) do return v.frame.as(not null).arguments.first
end
+redef class AAttrExpr
+ redef fun expr(v) do
+ var recv = v.expr(self.n_expr, null)
+ var mproperty = self.mproperty.as(not null)
+ return v.read_attribute(mproperty, recv)
+ end
+end
+
+redef class AAttrAssignExpr
+ redef fun expr(v) do
+ var recv = v.expr(self.n_expr, null)
+ var i = v.expr(self.n_value, null)
+ var mproperty = self.mproperty.as(not null)
+ v.write_attribute(mproperty, recv, i)
+ return i
+ end
+end
+
+redef class AAttrReassignExpr
+ redef fun stmt(v) do
+ var recv = v.expr(self.n_expr, null)
+ var value = v.expr(self.n_value, null)
+ var mproperty = self.mproperty.as(not null)
+ var attr = v.read_attribute(mproperty, recv)
+ var res = v.compile_callsite(self.reassign_callsite.as(not null), [attr, value])
+ assert res != null
+ v.write_attribute(mproperty, recv, res)
+ end
+end
+
+redef class AIssetAttrExpr
+ redef fun expr(v) do
+ var recv = v.expr(self.n_expr, null)
+ var mproperty = self.mproperty.as(not null)
+ return v.isset_attribute(mproperty, recv)
+ end
+end
+
redef class AReturnExpr
redef fun stmt(v) do
var nexpr = self.n_expr
end
end
+redef class AIfExpr
+ redef fun stmt(v) do
+ var cond = v.expr_bool(self.n_expr)
+ v.add("if ({cond})\{")
+ v.stmt(self.n_then)
+ v.add("\} else \{")
+ v.stmt(self.n_else)
+ v.add("\}")
+ end
+
+ redef fun expr(v) do
+ var res = v.new_var(self.mtype.as(not null))
+ var cond = v.expr_bool(self.n_expr)
+ v.add("if ({cond})\{")
+ v.assign(res, v.expr(self.n_then.as(not null), null))
+ v.add("\} else \{")
+ v.assign(res, v.expr(self.n_else.as(not null), null))
+ v.add("\}")
+ return res
+ end
+end
+
+redef class ADoExpr
+ redef fun stmt(v)
+ do
+ v.add_escape_label(break_mark)
+ v.add "\{"
+ v.stmt(self.n_block)
+ v.add "\}"
+ end
+end
+
+redef class AWhileExpr
+ redef fun stmt(v)
+ do
+ v.add_escape_label(break_mark)
+ v.add_escape_label(continue_mark)
+ v.add("for(;;) \{")
+ var cond = v.expr_bool(self.n_expr)
+ v.add("if (!{cond}) break;")
+ v.stmt(self.n_block)
+ v.add("\}")
+ end
+end
+
+redef class ALoopExpr
+ redef fun stmt(v)
+ do
+ v.add_escape_label(break_mark)
+ v.add_escape_label(continue_mark)
+ v.add("for(;;) \{")
+ v.stmt(self.n_block)
+ v.add("\}")
+ end
+end
+
+redef class AEscapeExpr
+ redef fun stmt(v) do v.add("break BREAK_{v.escapemark_name(escapemark)};")
+end
+
redef class AVardeclExpr
redef fun stmt(v) do
var variable = self.variable.as(not null)
end
end
-redef class AIntExpr
- redef fun expr(v) do return v.int_instance(self.value.as(not null))
+
+redef class AAssertExpr
+ redef fun stmt(v) do
+ var cond = v.expr_bool(self.n_expr)
+ v.add("if (!{cond}) \{")
+ v.stmt(self.n_else)
+ var nid = self.n_id
+ if nid != null then
+ v.add_abort("Assert '{nid.text}' failed")
+ else
+ v.add_abort("Assert failed")
+ end
+ v.add("\}")
+ end
+end
+
+redef class AImpliesExpr
+ redef fun expr(v) do
+ var res = v.new_var(mtype.as(not null))
+ var i1 = v.expr_bool(n_expr)
+ v.add("if (!{i1}) \{")
+ v.add("{res} = true;")
+ v.add("\} else \{")
+ var i2 = v.expr_bool(n_expr2)
+ v.add("{res} = {i2};")
+ v.add("\}")
+ return res
+ end
+end
+
+redef class AOrElseExpr
+ redef fun expr(v)
+ do
+ var res = v.new_var(self.mtype.as(not null))
+ var i1 = v.expr(self.n_expr, null)
+ v.add("if ({i1} != null && !{i1}.is_null()) \{")
+ v.assign(res, i1)
+ v.add("\} else \{")
+ var i2 = v.expr(self.n_expr2, null)
+ v.assign(res, i2)
+ v.add("\}")
+ return res
+ end
+end
+
+redef class AOrExpr
+ redef fun expr(v) do
+ var res = v.new_var(self.mtype.as(not null))
+ var i1 = v.expr_bool(self.n_expr)
+ v.add("if ({i1}) \{")
+ v.add("{res} = true;")
+ v.add("\} else \{")
+ var i2 = v.expr_bool(self.n_expr2)
+ v.add("{res} = {i2};")
+ v.add("\}")
+ return res
+ end
+end
+
+redef class AAndExpr
+ redef fun expr(v) do
+ var res = v.new_var(self.mtype.as(not null))
+ var i1 = v.expr_bool(self.n_expr)
+ v.add("if (!{i1}) \{")
+ v.add("{res} = false;")
+ v.add("\} else \{")
+ var i2 = v.expr_bool(self.n_expr2)
+ v.add("{res} = {i2};")
+ v.add("\}")
+ return res
+ end
+end
+
+redef class ANotExpr
+ redef fun expr(v) do
+ var cond = v.expr_bool(self.n_expr)
+ return v.new_expr("!{cond}", self.mtype.as(not null))
+ end
end
-redef class AByteExpr
- redef fun expr(v) do return v.byte_instance(self.value.as(not null))
+redef class AIntegerExpr
+ redef fun expr(v) do
+ if value isa Int then
+ return v.int_instance(self.value.as(Int))
+ else if value isa Byte then
+ return v.byte_instance(self.value.as(Byte))
+ else
+ # Should not happen
+ abort
+ end
+ end
end
redef class AFloatExpr
redef fun expr(v) do return v.null_instance
end
+redef class AAsCastExpr
+ redef fun expr(v)
+ do
+ var i = v.expr(n_expr, null)
+ v.add_cast(i, mtype.as(not null))
+ return i
+ end
+end
+
+redef class AAsNotnullExpr
+ redef fun expr(v) do
+ var i = v.expr(n_expr, null)
+ if i.mtype.is_java_primitive then return i
+
+ v.add("if ({i} == null || {i}.is_null()) \{")
+ v.add_abort("Cast failed")
+ v.add("\}")
+ return i
+ end
+end
+
+redef class AIsaExpr
+ redef fun expr(v)
+ do
+ var i = v.expr(self.n_expr, null)
+ var cast_type = self.cast_type
+ if cast_type == null then return null # no-no on broken node
+ return v.type_test(i, cast_type)
+ end
+end
+
+redef class AParExpr
+ redef fun expr(v) do return v.expr(self.n_expr, null)
+end
+
redef class AAbortExpr
redef fun stmt(v) do v.add_abort("Aborted")
end