import modelize
import astbuilder
private import annotation
+private import astvalidation
redef class ToolContext
# Transforms a function annotated with "threaded"
if nat.n_atid.n_id.text != "threaded" then return
if not nmethdef isa AMethPropdef then
- toolcontext.error(nmethdef.location, "Syntax error: only a method can be threaded.")
- return
- end
- if nmethdef.n_signature.n_params.length != 0 then
- toolcontext.error(nmethdef.location, "Syntax error: parametrized method not supported yet.")
- return
- end
- if nmethdef.n_signature.n_type != null then
- toolcontext.error(nmethdef.location, "Syntax error: method with a return value not supported yet.")
+ toolcontext.error(nat.location, "Syntax Error: only a method can be threaded.")
return
end
+ #TODO: check for self calls
+
# Get the module associated with this method
var amod = nmethdef.parent.parent
assert amod isa AModule
# Construct the name of the generated class
- var modulename = amod.n_moduledecl.n_name.n_id.text
- var classname = "Threaded" + modulename
+ var classname = "Threaded"
# Try to get the name of the class
if nmethdef.parent isa AStdClassdef then
- classname += nmethdef.parent.as(AStdClassdef).n_id.text
+ classname += nmethdef.parent.as(AStdClassdef).n_qid.n_id.text
end
# Try to get the name of the method
classname += nmethdef.n_methid.as(AIdMethid).n_id.text
end
- # Create a string corresponding to the threaded class
- var s ="""
+ # Handle methods with a return value
+ var has_rvalue = nmethdef.n_signature.n_type != null
+ var vtype = ""
+ if has_rvalue then
+ vtype = "redef type E: " + nmethdef.n_signature.n_type.n_qid.n_id.text
+ end
+
+ # create a return type
+ var n_id = new TClassid
+ n_id.text = classname
+ var n_qid = new AQclassid
+ n_qid.n_id = n_id
+ var n_type = new AType
+ n_type.n_qid = n_qid
+ nmethdef.n_signature.n_type = n_type
+
+ var params = new Array[String]
+ for param in nmethdef.n_signature.n_params do
+ var typ = param.n_type.n_qid.n_id.text
+ if param.n_type.n_kwnullable != null then typ = "nullable {typ}"
+ params.add """
+var {{{param.n_id.text}}}: {{{typ}}}
+"""
+ end
+
+ # String corresponding to the generated class
+ var classdef_source = """
class {{{classname}}}
super Thread
+ {{{vtype}}}
+
+ {{{params.join("\n")}}}
redef fun main do
end
end
"""
# Parse newly obtained classdef
- var classdef = toolcontext.parse_classdef(s).as(AStdClassdef)
+ var classdef = toolcontext.parse_classdef(classdef_source)
+ assert classdef isa AStdClassdef
# Get the `main` fun of the class
- var mainfun : nullable AMethPropdef = null
+ var mainfun: nullable AMethPropdef = null
for prop in classdef.n_propdefs do
if prop isa AMethPropdef then mainfun = prop
end
mainfun.n_block = nmethdef.n_block
# Add "return null" to the end of the `main` function
- var s_nullreturn = "return null"
- var nullreturn = toolcontext.parse_something(s_nullreturn)
- assert nullreturn isa AExpr
- mainfun.n_block.as(ABlockExpr).n_expr.add(nullreturn)
+ if not has_rvalue then
+ var s_nullreturn = "return null"
+ var nullreturn = toolcontext.parse_something(s_nullreturn)
+ assert nullreturn isa AExpr
+ mainfun.n_block.as(ABlockExpr).n_expr.add(nullreturn)
+ end
# Create new body for the annotated fun
- var s_newbody ="""
+ var s_newbody : String
+ if nmethdef.n_signature.n_params.not_empty then
+ var init_params = new Array[String]
+ for param in nmethdef.n_signature.n_params do
+ init_params.add(param.n_id.text)
+ end
+ s_newbody ="""
+var thread = new {{{classname}}}({{{init_params.join(",")}}})
+thread.start
+return thread
+"""
+ else
+ s_newbody = """
var thread = new {{{classname}}}
thread.start
+return thread
"""
+ end
var newbody = toolcontext.parse_something(s_newbody)
nmethdef.n_block = newbody.as(ABlockExpr)
+ nmethdef.validate
+
# Add the new class to the module
amod.n_classdefs.add(classdef)
+ classdef.validate
end
end