class Emfrp::MatchExp

Public Instance Methods

codegen(ct, stmts) click to toggle source
# File lib/emfrp/compile/c/syntax_exp_codegen.rb, line 53
def codegen(ct, stmts)
  vname = "_tmp%03d" % ct.uniq_id_gen
  stmts << "#{ct.tref(self)} #{vname};"
  left = self[:exp]
  if left.is_a?(VarRef)
    left_vname = left[:binder].get.var_name(ct, left[:name][:desc])
  else
    left_vname = "_tmp%03d" % ct.uniq_id_gen
    stmts.unshift "#{ct.tref(left)} #{left_vname};"
    stmts.push "#{left_vname} = #{left.codegen(ct, stmts)};"
  end
  self[:cases].each_with_index do |c, i|
    then_stmts = []
    cond_exps = pattern_to_cond_exps(ct, left_vname, then_stmts, c, c[:pattern])
    cond_exp = cond_exps.size == 0 ? "1" : cond_exps.join(" && ")
    if c[:exp].is_a?(SkipExp)
      then_stmts << "return 0;"
    else
      then_stmts << "#{vname} = #{c[:exp].codegen(ct, then_stmts)};"
    end
    if i == 0
      stmts << ct.make_block("if (#{cond_exp}) {", then_stmts, "}")
    elsif i == self[:cases].length - 1
      stmts << ct.make_block("else {", then_stmts, "}")
    else
      stmts << ct.make_block("else if (#{cond_exp}) {", then_stmts, "}")
    end
  end
  return vname
end
pattern_to_cond_exps(ct, receiver, stmts, case_def, pattern) click to toggle source
# File lib/emfrp/compile/c/syntax_exp_codegen.rb, line 84
def pattern_to_cond_exps(ct, receiver, stmts, case_def, pattern)
  if pattern[:ref]
    vname = case_def.var_name(ct, pattern[:ref][:desc])
    stmts << "#{ct.tref(pattern)} #{vname} = #{receiver};"
  end
  case pattern
  when ValuePattern
    conds = []
    type_def = ct.tdef(pattern)
    accessor = type_def[:static] ? "." : "->"
    if type_def[:tvalues].size > 1
      tvalue_id = type_def[:tvalues].index{|x| x[:name] == pattern[:name]}
      if type_def.enum?(ct)
        conds << "#{receiver} == #{tvalue_id}"
      else
        conds << "#{receiver}" + accessor + "tvalue_id == " + tvalue_id.to_s
      end
    end
    new_receiver = "#{receiver}" + accessor + "value." + pattern[:name][:desc]
    pattern[:args].each_with_index do |x, i|
      conds += pattern_to_cond_exps(ct, new_receiver + ".member#{i}", stmts, case_def, x)
    end
    return conds
  when IntegralPattern
    return ["#{receiver} == #{pattern[:val][:entity][:desc]}"]
  else
    return []
  end
end