123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951 |
- #======================================================
- AFFECTATION
- ======================================================#
- abstract type StarpuExpr end
- abstract type StarpuExprTyped <: StarpuExpr end
- struct StarpuExprTypedVar <: StarpuExprTyped
- name :: Symbol
- typ :: Type
- end
- struct StarpuExprTypedExpr <: StarpuExprTyped # TODO : remove typed expression ?
- expr :: StarpuExpr
- typ :: Type
- end
- struct StarpuExprAffect <: StarpuExpr
- var :: StarpuExpr
- expr :: StarpuExpr
- end
- struct StarpuExprBlock <: StarpuExpr
- exprs :: Vector{StarpuExpr}
- end
- struct StarpuExprCall <: StarpuExpr
- func :: Symbol
- args :: Vector{StarpuExpr}
- end
- struct StarpuExprCudaCall <: StarpuExpr
- ker_name :: Symbol
- nblocks :: StarpuExpr
- threads_per_block :: StarpuExpr
- args :: Vector{StarpuExpr}
- end
- struct StarpuExprField <: StarpuExpr
- left :: StarpuExpr
- field :: Symbol
- is_an_arrow :: Bool
- end
- struct StarpuExprInterval <: StarpuExpr
- start :: StarpuExpr
- step :: StarpuExpr
- stop :: StarpuExpr
- id :: String
- function StarpuExprInterval(start :: StarpuExpr, step :: StarpuExpr, stop :: StarpuExpr ; id :: String = rand_string())
- return new(start, step, stop, id)
- end
- end
- struct StarpuExprFor <: StarpuExpr
- iter :: Symbol
- set:: StarpuExprInterval
- body :: StarpuExpr
- is_independant :: Bool
- set_declarations :: Vector{StarpuExpr}
- end
- struct StarpuExprFunction <: StarpuExpr
- ret_type :: Type
- func :: Symbol
- args :: Vector{StarpuExprTypedVar}
- body :: StarpuExpr
- end
- struct StarpuExprIf <: StarpuExpr
- cond :: StarpuExpr
- then_statement :: StarpuExpr
- end
- struct StarpuExprIfElse <: StarpuExpr
- cond :: StarpuExpr
- then_statement :: StarpuExpr
- else_statement :: StarpuExpr
- end
- struct StarpuExprRef <: StarpuExpr
- ref :: StarpuExpr
- indexes :: Vector{StarpuExpr}
- end
- struct StarpuExprReturn <: StarpuExpr
- value :: StarpuExpr
- end
- struct StarpuExprBreak <: StarpuExpr
- end
- struct StarpuExprVar <: StarpuExpr
- name :: Symbol
- end
- struct StarpuExprInvalid <: StarpuExpr
- end
- struct StarpuExprValue <: StarpuExpr
- value :: Any
- end
- struct StarpuExprWhile <: StarpuExpr
- cond :: StarpuExpr
- body :: StarpuExpr
- end
- function starpu_parse_affect(x :: Expr)
- if (x.head != :(=))
- error("Invalid \"affectation\" expression")
- end
- var = starpu_parse(x.args[1])
- expr = starpu_parse(x.args[2])
- return StarpuExprAffect(var, expr)
- end
- function equals(x :: StarpuExprAffect, y :: StarpuExpr)
- if typeof(y) != StarpuExprAffect
- return false
- end
- return equals(x.var, y.var) && equals(x.expr, y.expr)
- end
- function print(io :: IO, x :: StarpuExprAffect ; indent = 0, restrict = false)
- print(io, x.var, indent = indent)
- print(io, " = ")
- need_to_transtyp = isa(x.var, StarpuExprTypedVar) # transtyping to avoid warning (or errors for cuda) during compilation time
- if need_to_transtyp
- print(io, "(", starpu_type_traduction(x.var.typ), ") (")
- end
- print(io, x.expr, indent = indent)
- if need_to_transtyp
- print(io, ")")
- end
- end
- function apply(func :: Function, expr :: StarpuExprAffect)
- var = apply(func, expr.var)
- new_expr = apply(func, expr.expr)
- return func(StarpuExprAffect(var, new_expr))
- end
- #======================================================
- BLOCK
- (series of instruction, not C variable scoping block)
- ======================================================#
- function is_unwanted(x :: Symbol)
- return false
- end
- function is_unwanted(x :: LineNumberNode)
- return true
- end
- function is_unwanted(x :: Expr)
- return false
- end
- function starpu_parse_block(x :: Expr)
- if (x.head != :block)
- error("Invalid \"block\" expression")
- end
- exprs = map(starpu_parse, filter(!is_unwanted, x.args))
- return StarpuExprBlock(exprs)
- end
- function print(io :: IO, x :: StarpuExprBlock ; indent = 0, restrict=false)
- for i in (1 : length(x.exprs))
- print(io, x.exprs[i], indent = indent)
- print(io, ";")
- if (i != length(x.exprs))
- print_newline(io, indent)
- end
- end
- end
- function apply(func :: Function, expr :: StarpuExprBlock)
- return func(StarpuExprBlock(map((x -> apply(func, x)), expr.exprs)))
- end
- #======================================================
- FUNCTION CALL
- ======================================================#
- function starpu_parse_call(x :: Expr)
- if (x.head != :call)
- error("Invalid \"call\" expression")
- end
- func = starpu_parse(x.args[1])
- if (x.args[1] == Symbol(":"))
- return starpu_parse_interval(x)
- end
- if (!isa(func, StarpuExprVar))
- error("Invalid \"call\" expression : function must be a variable")
- end
- args = map(starpu_parse, x.args[2:end])
- return StarpuExprCall(func.name, args)
- end
- starpu_infix_operators = (:(+), :(*), :(-), :(/), :(<), :(>), :(<=), :(>=), :(%))
- function print_prefix(io :: IO, x :: StarpuExprCall ; indent = 0, restrict=false)
- print(io, x.func, "(")
- for i in (1 : length(x.args))
- if (i != 1)
- print(io, ", ")
- end
- print(io, x.args[i], indent = indent)
- end
- print(io, ")")
- end
- function print_infix(io :: IO, x :: StarpuExprCall ; indent = 0,restrict=false)
- for i in (1 : length(x.args))
- if (i != 1)
- print(io, " ", x.func, " ")
- end
- print(io, "(")
- print(io, x.args[i], indent = indent)
- print(io, ")")
- end
- end
- function print(io :: IO, x :: StarpuExprCall ; indent = 0,restrict=false)
- if (length(x.args) >= 2 && x.func in starpu_infix_operators)
- print_infix(io, x, indent = indent)
- else
- print_prefix(io, x, indent = indent)
- end
- end
- function apply(func :: Function, expr :: StarpuExprCall)
- return func(StarpuExprCall(expr.func, map((x -> apply(func, x)), expr.args)))
- end
- #======================================================
- CUDA KERNEL CALL
- ======================================================#
- function print(io :: IO, expr :: StarpuExprCudaCall ; indent = 0,restrict=false)
- print_newline(io, indent)
- print(io, expr.ker_name)
- print_newline(io, indent + starpu_indent_size)
- print(io, "<<< ")
- print(io, expr.nblocks, indent = indent + 2 * starpu_indent_size)
- print(io, ", ")
- print(io, expr.threads_per_block, indent = indent + 2 * starpu_indent_size)
- print(io, ", 0, starpu_cuda_get_local_stream()")
- print_newline(io, indent + starpu_indent_size)
- print(io, ">>> (")
- for i in (1 : length(expr.args))
- if (i != 1)
- print(io, ", ")
- if (i % 4 == 1)
- print_newline(io, indent + 2 * starpu_indent_size + 1)
- end
- end
- print(io, expr.args[i], indent = indent + 2 * starpu_indent_size)
- end
- print(io, ");")
- print_newline(io, indent)
- end
- function apply(func :: Function, expr :: StarpuExprCudaCall)
- nblocks = func(expr.nblocks)
- threads_per_block = func(expr.threads_per_block)
- args = map((x -> apply(func, x)), expr.args)
- return StarpuExprCudaCall(expr.ker_name, nblocks, threads_per_block, args)
- end
- #======================================================
- STRUCTURE FIELDS
- ======================================================#
- function starpu_parse_field(x :: Expr)
- if x.head != :(.) || length(x.args) != 2
- error("Invalid parsing of dot expression")
- end
- left = starpu_parse(x.args[1])
- if (!isa(x.args[2], QuoteNode) || !isa(x.args[2].value, Symbol))
- error("Invalid parsing of dot expression")
- end
- return StarpuExprField(left, x.args[2].value, false)
- end
- function print(io :: IO, x :: StarpuExprField ; indent = 0,restrict=false)
- print(io, "(")
- print(io, x.left, indent = indent)
- print(io, ")", x.is_an_arrow ? "->" : '.', x.field)
- end
- function apply(func :: Function, expr :: StarpuExprField)
- return func(StarpuExprField(func(expr.left), expr.field, expr.is_an_arrow))
- end
- #======================================================
- FOR LOOPS
- ======================================================#
- function starpu_parse_for(x :: Expr; is_independant = false)
- if (x.head != :for)
- error("Invalid \"for\" expression")
- end
- affect = x.args[1]
- if (affect.head != :(=))
- error("Invalid \"for\" iterator affectation")
- end
- iter = starpu_parse(affect.args[1])
- if (!isa(iter, StarpuExprVar))
- error("Invalid \"for\" iterator")
- end
- set = starpu_parse(affect.args[2])
- if (!isa(set, StarpuExprInterval))
- error("Set of values in \"for\" loop must be an interval")
- end
- body = starpu_parse(x.args[2])
- return StarpuExprFor(iter.name, set, body, is_independant, StarpuExpr[])
- end
- function print(io :: IO, x :: StarpuExprFor ; indent = 0,restrict=false)
- print_newline(io, indent)
- print(io, StarpuExprBlock(x.set_declarations), indent = indent)
- id = x.set.id
- start = "start_" * id
- stop = "stop_" * id
- step = "step_" * id
- dim = "dim_" * id
- iter = "iter_" * id
- print_newline(io, indent, 2)
- if isa(x.set.step, StarpuExprValue)
- print(io, "for ($(x.iter) = $start ; ")
- comparison_op = (x.set.step.value >= 0) ? "<=" : ">="
- print(io, "$(x.iter) $comparison_op $stop ; ")
- print(io, "$(x.iter) += $(x.set.step.value))")
- else
- print(io, "for ($iter = 0, $(x.iter) = $start ; ")
- print(io, "$iter < $dim ; ")
- print(io, "$iter += 1, $(x.iter) += $step)")
- end
- print_newline(io, indent)
- print(io, "{")
- print_newline(io, indent + starpu_indent_size)
- print(io, x.body, indent = indent + starpu_indent_size)
- print_newline(io, indent)
- print(io, "}")
- print_newline(io, indent)
- end
- function apply(func :: Function, expr :: StarpuExprFor)
- set_declarations = map( (x -> apply(func, x)), expr.set_declarations)
- set = apply(func, expr.set)
- body = apply(func, expr.body)
- return func(StarpuExprFor(expr.iter, set, body, expr.is_independant, set_declarations))
- end
- #======================================================
- FUNCTION DECLARATION
- ======================================================#
- function starpu_parse_function(x :: Expr)
- if (x.head != :function)
- error("Invalid \"function\" expression")
- end
- typed_decl = starpu_parse(x.args[1])
- if (!isa(typed_decl, StarpuExprTypedExpr))
- error("Invalid \"function\" prototype : a return type must me explicited")
- end
- prototype = typed_decl.expr
- if (!isa(prototype, StarpuExprCall))
- error("Invalid \"function\" prototype")
- end
- arg_list = StarpuExprTypedVar[]
- for type_arg in prototype.args
- if (!isa(type_arg, StarpuExprTypedVar))
- error("Invalid \"function\" argument list")
- end
- push!(arg_list, type_arg)
- end
- body = starpu_parse(x.args[2])
- return StarpuExprFunction(typed_decl.typ, prototype.func, arg_list, body)
- end
- function print(io :: IO, x :: StarpuExprFunction ; indent = 0,restrict=false)
- print(io, starpu_type_traduction(x.ret_type), " ")
- print(io, x.func, '(')
- for i in (1 : length(x.args))
- if (i != 1)
- print(io, ", ")
- if (i % 4 == 1)
- print_newline(io, indent + starpu_indent_size + length(String(x.func)) + 13)
- end
- end
- print(io, x.args[i], indent = indent + starpu_indent_size, restrict = true)
- end
- print(io, ")")
- print_newline(io, indent)
- print(io, "{")
- print_newline(io, indent + starpu_indent_size)
- print(io, x.body, indent = indent + starpu_indent_size)
- print_newline(io, indent)
- print(io, "}\n\n")
- print_newline(io, indent)
- end
- function apply(func :: Function, expr :: StarpuExprFunction)
- args = map((x -> apply(func, x)), expr.args)
- body = apply(func, expr.body)
- return func(StarpuExprFunction(expr.ret_type, expr.func, args, body))
- end
- #======================================================
- IF STATEMENT
- ======================================================#
- function starpu_parse_if(x :: Expr)
- if (x.head != :if)
- error("Invalid \"if\" expression")
- end
- len = length(x.args)
- if (len < 2)
- error("Invalid \"if\" statement")
- end
- cond = starpu_parse(x.args[1])
- then_statement = starpu_parse(x.args[2])
- if (len == 2)
- return StarpuExprIf(cond, then_statement)
- end
- else_statement = starpu_parse(x.args[3])
- return StarpuExprIfElse(cond, then_statement, else_statement)
- end
- function print(io :: IO, x :: Union{StarpuExprIf, StarpuExprIfElse}; indent = 0,restrict=false)
- print_newline(io, indent)
- print(io, "if (")
- print(io, x.cond, indent = indent + starpu_indent_size)
- print(io, ")")
- print_newline(io, indent)
- print(io, "{")
- print_newline(io, indent + starpu_indent_size)
- print(io, x.then_statement, indent = indent + starpu_indent_size)
- print_newline(io, indent)
- print(io, "}")
- if (!isa(x, StarpuExprIfElse))
- return
- end
- print(io, " else")
- print_newline(io, indent)
- print(io, "{")
- print_newline(io, indent + starpu_indent_size)
- print(io, x.else_statement, indent = indent + starpu_indent_size)
- print_newline(io, indent)
- print(io, "}")
- print_newline(io, indent)
- end
- function apply(func :: Function, expr :: StarpuExprIf)
- cond = apply(func, expr.cond)
- then_statement = apply(func, expr.then_statement)
- return func(StarpuExprIf(cond, then_statement))
- end
- function apply(func :: Function, expr :: StarpuExprIfElse)
- cond = apply(func, expr.cond)
- then_statement = apply(func, expr.then_statement)
- else_statement = apply(func, expr.else_statement)
- return func(StarpuExprIfElse(cond, then_statement, else_statement))
- end
- #======================================================
- INTERVALS
- ======================================================#
- function starpu_parse_interval(x :: Expr)
- if (x.head != :(call))
- error("Invalid \"interval\" expression")
- end
- start = starpu_parse(x.args[2])
- steop = starpu_parse(x.args[3])
- if (length(x.args) == 3)
- return StarpuExprInterval(start, StarpuExprValue(1), steop)
- end
- stop = starpu_parse(x.args[4])
- return StarpuExprInterval(start, steop, stop)
- end
- function apply(func :: Function, expr :: StarpuExprInterval)
- start = apply(func, expr.start)
- step = apply(func, expr.step)
- stop = apply(func, expr.stop)
- return func(StarpuExprInterval(start, step, stop, id = expr.id))
- end
- #======================================================
- ARRAYS AND REFERENCES
- ======================================================#
- function starpu_parse_ref(x :: Expr)
- if (x.head != :ref)
- error("Invalid \"reference\" expression")
- end
- ref = starpu_parse(x.args[1])
- indexes = map(starpu_parse, x.args[2:end])
- #=
- StarpuExpr[]
- for i in (2 : length(x.args))
- push!(indexes, starpu_parse(x.args[i]))
- end=#
- return StarpuExprRef(ref, indexes)
- end
- function equals(x :: StarpuExprRef, y :: StarpuExpr)
- if typeof(y) != StarpuExprRef
- return false
- end
- if !equals(x.ref, y.ref) || length(x.indexes) != length(y.indexes)
- return false
- end
- return all(map(equals, x.indexes, y.indexes))
- end
- function print(io :: IO, x :: StarpuExprRef ; indent = 0,restrict=false)
- print(io, x.ref, indent = indent)
- for i in (1 : length(x.indexes))
- print(io, "[")
- print(io, x.indexes[i], indent = indent)
- print(io, "]")
- end
- end
- function apply(func :: Function, expr :: StarpuExprRef)
- ref = apply(func, expr.ref)
- indexes = map((x -> apply(func, x)), expr.indexes)
- return func(StarpuExprRef(ref, indexes))
- end
- #======================================================
- BREAK EXPRESSION
- ======================================================#
- function starpu_parse_break(x :: Expr)
- if (x.head != :break)
- error("Invalid \"break\" expression")
- end
- return StarpuExprBreak()
- end
- function print(io :: IO, x :: StarpuExprBreak ; indent = 0)
- print(io, "break")
- end
- function apply(func :: Function, expr :: StarpuExprBreak)
- return func(StarpuExprBreak())
- end
- #======================================================
- RETURN EXPRESSION
- ======================================================#
- function starpu_parse_return(x :: Expr)
- if (x.head != :return)
- error("Invalid \"return\" expression")
- end
- value = starpu_parse(x.args[1])
- # Remove type associated to a single, for a return
- # allows matching with ExprVar
- if (isa(value, StarpuExprTypedVar))
- value = StarpuExprVar(value.name)
- end
- return StarpuExprReturn(value)
- end
- function print(io :: IO, x :: StarpuExprReturn ; indent = 0,restrict=false)
- print(io, "return ")
- print(io, x.value, indent = indent)
- end
- function apply(func :: Function, expr :: StarpuExprReturn)
- return func(StarpuExprReturn(apply(func, expr.value)))
- end
- function apply(func :: Function, expr :: StarpuExpr)
- return func(expr)
- end
- print(io :: IO, x :: StarpuExprVar ; indent = 0) = print(io, x.name)
- function print(io :: IO, x :: StarpuExprValue ; indent = 0,restrict=false)
- value = x.value
- if value == nothing
- return
- end
- if isa(value, AbstractString)
- print(io, '"', value, '"')
- return
- end
- if isa(value, Char)
- print(io, '\'', value, '\'')
- return
- end
- print(io, value)
- end
- print(io :: IO, x :: StarpuExprInvalid ; indent = 0) = print(io, "INVALID")
- function starpu_parse(raw_value :: Any)
- return StarpuExprValue(raw_value)
- end
- function starpu_parse(sym :: Symbol)
- return StarpuExprVar(sym)
- end
- #======================================================
- TYPED EXPRESSION
- ======================================================#
- function starpu_parse_typed(x :: Expr)
- if (x.head != :(::))
- error("Invalid type assigned expression")
- end
- expr = starpu_parse(x.args[1])
- typ = nothing
- try
- typ = eval(x.args[2]) :: Type
- catch
- print(x.args[2])
- error("Invalid type in type assigned expression")
- end
- if (isa(expr, StarpuExprVar))
- return StarpuExprTypedVar(expr.name, typ)
- end
- return StarpuExprTypedExpr(expr, typ)
- end
- starpu_type_traduction_dict = Dict(
- Int32 => "int32_t",
- UInt32 => "uint32_t",
- Float32 => "float",
- Int64 => "int64_t",
- UInt64 => "uint64_t",
- Float64 => "double",
- Nothing => "void"
- )
- function starpu_type_traduction(x)
- if x <: Array
- return starpu_type_traduction_array(x)
- end
- if x <: Ptr
- return starpu_type_traduction(eltype(x)) * "*"
- end
- return starpu_type_traduction_dict[x]
- end
- function starpu_type_traduction_array(x :: Type{Array{T,N}}) where {T,N}
- output = starpu_type_traduction(T)
- for i in (1 : N)
- output *= "*"
- end
- return output
- end
- function print(io :: IO, x :: StarpuExprTyped ; indent = 0,restrict=false)
- if (isa(x, StarpuExprTypedVar))
- print(io,starpu_type_traduction(x.typ), " ")
- #if (restrict)
- # print(io,"restrict ");
- #end
- print(io, x.name)
- else
- print(io, x.expr, indent = indent)
- end
- end
- function apply(func :: Function, expr :: StarpuExprTypedExpr)
- new_expr = apply(func, expr.expr)
- return func(StarpuExprTypedExpr(new_expr, expr.typ))
- end
- #======================================================
- While loop
- ======================================================#
- function starpu_parse_while(x :: Expr)
- if (x.head != :while)
- error("Invalid \"while\" loop")
- end
- len = length(x.args)
- if (len < 2)
- error("Invalid \"while\" loop")
- end
- cond = starpu_parse(x.args[1])
- body = starpu_parse(x.args[2])
- return StarpuExprWhile(cond, body)
- end
- function print(io :: IO, x :: StarpuExprWhile ; indent = 0)
- print_newline(io, indent)
- print(io, "while (")
- print(io, x.cond, indent = indent + starpu_indent_size)
- print(io, ")")
- print_newline(io, indent)
- print(io, "{")
- print_newline(io, indent + starpu_indent_size)
- print(io, x.body, indent = indent + starpu_indent_size)
- print_newline(io, indent)
- print(io, "}")
- print_newline(io, indent)
- end
- function apply(func :: Function, expr :: StarpuExprWhile)
- cond = apply(func, expr.cond)
- body = apply(func, expr.body)
- return func(StarpuExprWhile(cond, body))
- end
|