Skip to content

Commit

Permalink
Compiler: add some support for emit with keyword arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
noteflakes committed Feb 19, 2024
1 parent 41f1958 commit 6d0648c
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 29 deletions.
46 changes: 26 additions & 20 deletions examples/perf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,39 +113,45 @@ def render_papercraft_app
App.render(title: 'title from context')
end

def render_papercraft_content
Content.render(title: 'title from context')
# def render_papercraft_content
# Content.render(title: 'title from context')
# end

AppCompiled = App.compile
puts
puts AppCompiled.to_code
puts
AppCompiledProc = AppCompiled.to_proc

def render_papercraft_compiled_app
AppCompiledProc.(+'', title: 'title from context')
end
end

r = Renderer.new

puts '* Papercraft:'
puts r.render_papercraft_app
puts r.render_erubis_app.gsub(/\n\s*/, '')
puts r.render_erb_app.gsub(/\n\s+/, '')

# puts r.render_papercraft_content
# puts r.render_erubis_content
# puts r.render_erb_content
puts
puts '* Papercraft (compiled):'
puts r.render_papercraft_compiled_app
puts

# puts "=== Template with 2 partials"
# Benchmark.ips do |x|
# x.config(:time => 3, :warmup => 1)

# x.report("papercraft") { r.render_papercraft_app }
# x.report("erubis") { r.render_erubis_app }
# x.report("erb") { r.render_erb_app }
puts '* ERubis:'
puts r.render_erubis_app.gsub(/\n\s*/, '')
puts

# x.compare!
# end
puts '* ERB:'
puts r.render_erb_app.gsub(/\n\s+/, '')

puts "=== Single template"
Benchmark.ips do |x|
x.config(:time => 5, :warmup => 2)

x.report("papercraft") { r.render_papercraft_content }
x.report("erubis") { r.render_erubis_content }
x.report("erb") { r.render_erb_content }
x.report("papercraft") { r.render_papercraft_app }
x.report("papercraft (compiled)") { r.render_papercraft_compiled_app }
x.report("erubis") { r.render_erubis_app }
x.report("erb") { r.render_erb_app }

x.compare!
end
44 changes: 35 additions & 9 deletions lib/papercraft/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -158,20 +158,21 @@ def compile(template, initial_level = 0)

def to_code
pad = ' ' * @level
"#{pad}->(__buffer__#{args}, &__block__) do\n#{prelude}#{@code_buffer}#{pad} __buffer__\n#{pad}end"
"#{pad}->(__buffer__#{proc_args}, &__block__) do\n#{prelude}#{@code_buffer}#{pad} __buffer__\n#{pad}end"
end

def args
def proc_args
return nil if !@args

# ", #{@args.map { "#{_1}:" }.join(", ")}"
", #{@args.join(", ")}"
end

def prelude
return nil if @sub_templates.empty?

converted = @sub_templates.map { |t| convert_sub_template(t)}
"#{' ' * @level} __sub_templates__ = [\n#{converted.join("\n")}\n ]\n"
"#{' ' * @level} __sub_templates__ = [\n#{converted.join(",\n")}\n ]\n"
end

def convert_sub_template(template)
Expand All @@ -195,7 +196,7 @@ def parse(node, line_break = true)
def parse_scope(node)
args = node.children[0]
if args && !args.empty?
@args = args
@args = args.compact
end
parse(node.children[2])
end
Expand Down Expand Up @@ -339,7 +340,12 @@ def emit_emit(args, block)
@sub_templates << value
idx = @sub_templates.size - 1
@line_break = false
emit_code("__sub_templates__[#{idx}].(__buffer__)")
emit_code("__sub_templates__[#{idx}].(__buffer__")
if !rest.empty?
emit_code(", ")
parse_list(args, false, 1..-1)
end
emit_code(")")
emit_code_block(block) if block
emit_code("\n")
else
Expand Down Expand Up @@ -482,8 +488,8 @@ def parse_false(node)
emit_expression { emit_literal('true') }
end

def parse_list(node, emit_array = true, range = nil)
emit_literal('[') if emit_array
def parse_list(node, emit_container = true, range = nil)
emit_literal('[') if emit_container
if range
items = node.children[range].compact
else
Expand All @@ -493,10 +499,30 @@ def parse_list(node, emit_array = true, range = nil)
item = items.shift
break unless item

parse(item)
parse(item, emit_container)
emit_literal(', ') if !items.empty?
end
emit_literal(']') if emit_array
emit_literal(']') if emit_container
end

def parse_hash(node, emit_container = false)
emit_literal('{') if emit_container
items = node.children.first.children
idx = 0
while idx < items.size
k = items[idx]
break if !k

v = items[idx + 1]
p k: k, v: v
emit_literal(', ') if idx > 0
idx += 2

parse(k)
emit_literal(' => ')
parse(v)
end
emit_literal('}') if emit_container
end

def parse_vcall(node)
Expand Down

0 comments on commit 6d0648c

Please sign in to comment.