CodeTools::AST << {

# Helper methods for bytecode generation
CodeTools::Generator << {
  push_myco: push_cpath_top; find_const(:Myco)
  push_void: push_myco;      find_const(:Void)
  push_null: push_nil
}

Self < Node {
  node_type self
  bytecode: |g| pos(g); g.push_self
}

NullLiteral < Node {
  node_type null
  bytecode: |g| pos(g); g.push_null
}

VoidLiteral < Node {
  node_type void
  bytecode: |g| pos(g); g.push_void
}

TrueLiteral < Node {
  node_type true
  bytecode: |g| pos(g); g.push_true
}

FalseLiteral < Node {
  node_type false
  bytecode: |g| pos(g); g.push_false
}

# TODO: use some other way to be eager
EVALUATE_NOW: CodeTools::AST.component_eval {
  constants.select |const_name| {
    const_get(const_name).?node_type ?? null
  }.each |const_name| {
    component = const_get(const_name)
    node_type = component.node_type
    fields    = component.fields

    BuilderMethods.declare_meme(node_type) |*args| {
      loc = args.shift
      kw = [:line, *fields].zip([loc.line, *args])
      component.new(kw.to_h)
    }
  }
}

}