Skip to content

Idea: use MacroTools.jl? #149

@alhirzel

Description

@alhirzel

I know at this point it could be a heroic effort, but after looking at the parser for @aml, I thought it would be appropriate to suggest usage of MacroTools.jl and their @capture macro. It might be the biggest help around here:

########################
# Single struct name - "aml name"
if isa(ei, String)
# struct_function[1]=missing # function
# Self-name checker
if ei == "~"
if T isa Symbol
struct_name = string(T)
elseif T isa Expr && T.head == :curly
struct_name = string(T.args[1]) # S
end
else
struct_name = ei # Type aml name
end
argsexpr.args[i] = nothing # removing "aml name" from expr args
struct_nodetype = AbsNormal
################################################################
# Literal Struct name - empty"aml name"
elseif isa(ei, Tuple)
################################################################
# Struct aml
########################
# Literal only empty"aml name"
if isa(ei, Tuple{Type,String})
# struct_function[1]=missing # function
# Self-name checker
if ei[2] == "~"
if T isa Symbol
struct_name = string(T)
elseif T isa Expr && T.head == :curly
struct_name = string(T.args[1]) # S
end
else
struct_name = ei[2] # Type aml name
end
struct_nodetype = ei[1]
struct_nodetype = aml_dispatch(struct_nodetype, struct_name)
argsexpr.args[i] = nothing # removing "aml name" from expr args
# Custom Code
elseif isa(ei, Tuple{Symbol, Expr})
iMacro += 1
# Row for code insertion (insert before iArg-th argument)
if ei[1] == :creator
args_custom_creator[iArg] = ei[2]
elseif ei[1] == :extractor
args_custom_extractor[iArg] = ei[2]
elseif ei[1] == :updater
args_custom_updater[iArg] = ei[2]
end
argsexpr.args[i] = nothing # removing custom code macro from expr args
end
elseif ei isa Expr && ei.head == :tuple
########################
# Struct Function - "aml name", F
if isa(ei.args[1], String) && isa(ei.args[2], Union{Symbol,Function}) # "aml name", F
struct_function[1]=ei.args[2] # function
# Self-name checker
if ei.args[1] == "~"
if T isa Symbol
struct_name = string(T)
elseif T isa Expr && T.head == :curly
struct_name = string(T.args[1]) # S
end
else
struct_name = ei.args[1] # Type aml name
end
struct_nodetype = AbsNormal
argsexpr.args[i] = nothing # removing "aml name" from expr args
########################
# Literal and Struct Function - empty"aml name", F
elseif isa(ei.args[1], Tuple) && isa(ei.args[2], Union{Symbol,Function})
struct_function[1]=ei.args[2] # function
# Self-name checker
if ei.args[1][2] == "~"
if T isa Symbol
struct_name = string(T)
elseif T isa Expr && T.head == :curly
struct_name = string(T.args[1]) # S
end
else
struct_name = ei.args[1][2] # Type aml name
end
struct_nodetype = ei.args[1][1]
struct_nodetype = aml_dispatch(struct_nodetype, struct_name)
argsexpr.args[i] = nothing # removing "aml name" from expr args
################################################################
# Arguments
########################
# No Def Value
elseif ei.args[1] isa Union{Symbol,Expr} # var/var::T, "name"
# Def Value
# args_defaultvalue[iArg] = missing
# Type Checker
lhs = ei.args[1]
if lhs isa Symbol # var, "name"
var = ei.args[1]
args_type[iArg] = String # consider String as the type
args_param[iArg] = var
args_var[iArg] = var
argsexpr.args[i] = var # removing "name",...
elseif lhs isa Expr && lhs.head == :(::) && lhs.args[1] isa Symbol # var::T, "name"
var = lhs.args[1]
varType = lhs.args[2] # Type
args_type[iArg] = varType
args_param[iArg] = var
args_var[iArg] = var
argsexpr.args[i] = lhs # removing "name",...
end
# Literal Checker
if length(ei.args[2]) == 2 # literal
argAmlType = ei.args[2][1]
args_literaltype[iArg] = argAmlType # literal type
ni = ei.args[2][2]
# Self-name checker
if ni == "~"
args_name[iArg] = string(var)
else
args_name[iArg] = ni
end
else
args_literaltype[iArg] = AbsNormal # non-literal
ni = ei.args[2]
# Self-name checker
if ni == "~"
args_name[iArg] = string(var)
else
args_name[iArg] = ni
end
end
# Function Checker
if length(ei.args) == 3 && isa(ei.args[3], Union{Function, Symbol}) # var/var::T, "name", f
fun = ei.args[3] # function
args_function[iArg] = fun
# else # function name isn't given
# args_function[iArg] = missing
end
end # end Tuple sub possibilities
################################################################
# Def Value
elseif ei isa Expr && ei.head == :(=) # def value provided
# aml name Checker
if ei.args[2] isa Expr && ei.args[2].head == :tuple # var/var::T = defVal, "name"
# Def Value
defVal = ei.args[2].args[1]
args_defaultvalue[iArg] = defVal
lhs = ei.args[1]
argsexpr.args[i] = lhs # remove =defVal for type definition
# Type Checker
if lhs isa Symbol # var = defVal, "name"
var = ei.args[1]
args_type[iArg] = String # consider String as the type
args_param[iArg] = Expr(:kw, var, defVal)
args_var[iArg] = var
argsexpr.args[i] = var # removing "name",...
elseif lhs isa Expr && lhs.head == :(::) && lhs.args[1] isa Symbol # var::T = defVal, "name"
var = lhs.args[1]
varType = lhs.args[2] # Type
args_type[iArg] = varType
args_param[iArg] = Expr(:kw, var, defVal) # TODO also put type expression
args_var[iArg] = var
argsexpr.args[i] = lhs # removing "name",...
end
# Literal Checker
if length(ei.args[2].args[2]) == 2 # literal
argAmlType = ei.args[2].args[2][1]
args_literaltype[iArg] = argAmlType # literal type
ni = ei.args[2].args[2][2]
# Self-name checker
if ni == "~"
args_name[iArg] = string(var)
else
args_name[iArg] = ni
end
else
args_literaltype[iArg] = AbsNormal # non-literal
ni = ei.args[2].args[2]
# Self-name checker
if ni == "~"
args_name[iArg] = string(var)
else
args_name[iArg] = ni
end
end
# Function Checker
if length(ei.args[2].args) == 3 && isa(ei.args[2].args[3], Union{Function, Symbol}) # var/var::T = defVal, "name", f
fun = ei.args[2].args[3] # function
args_function[iArg] = fun
# else # function name isn't given
# args_function[iArg] = missing
end
########################
# No aml Name - But defVal
else # var/var::T = defVal # ignored for creating aml
# Type Checker
lhs = ei.args[1]
if lhs isa Symbol # var = defVal
defVal = ei.args[2]
args_defaultvalue[iArg] = defVal
# args_name[iArg] = missing # ignored for creating aml
# args_function[iArg] = missing # ignored for creating aml
var = ei.args[1]
args_type[iArg] = Any
args_param[iArg] = Expr(:kw, var, defVal)
args_var[iArg] = var
argsexpr.args[i] = var # remove =defVal for type definition
elseif lhs isa Expr && lhs.head == :(::) && lhs.args[1] isa Symbol # var::T = defVal
defVal = ei.args[2]
args_defaultvalue[iArg] = defVal
# args_name[iArg] = missing # ignored for creating aml
# args_function[iArg] = missing # ignored for creating aml
var = lhs.args[1]
varType = lhs.args[2] # Type
args_type[iArg] = varType
args_param[iArg] = Expr(:kw, var, defVal) # TODO also put type expression
args_var[iArg] = var
argsexpr.args[i] = lhs # remove =defVal for type definition
else
# something else, e.g. inline inner constructor
# F(...) = ...
continue
end
end
################################################################
# No aml name - No defVal
else # var/var::T # ignored for creating aml
# Type Checker
if ei isa Symbol # var
# args_name[iArg] = missing # argument ignored for aml
# args_function[iArg] = missing # ignored for creating aml
args_type[iArg] = String
var = ei
args_param[iArg] = var
args_var[iArg] = var
elseif ei.head == :(::) && ei.args[1] isa Symbol # var::T
# args_name[iArg] = missing # argument ignored for aml
# args_function[iArg] = missing # ignored for creating aml
var = ei.args[1]
varType = ei.args[2] # Type
args_type[iArg] = varType
args_param[iArg] = var
args_var[iArg] = var
elseif ei.head == :block # anything else should be evaluated again
# can arise with use of @static inside type decl
argsexpr, args_param, args_defaultvalue, args_type, args_var, args_name, args_function, args_literaltype, struct_name, struct_nodetype, struct_function, is_struct_mutable, args_custom_creator, args_custom_extractor, args_custom_updater, T = aml_parse(expr)
else
continue
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    wontfixThis will not be worked on

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions