Class: MiniRuby::Compiler

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/miniruby/compiler.rb

Overview

MiniRuby bytecode compiler. Takes in an AST and produces a bytecode function that can be executed by the VM.

Defined Under Namespace

Classes: Error

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, filename: '<main>', span: Span::ZERO) ⇒ Compiler

: (name: String, ?filename: String, ?span: Span) -> void



95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/miniruby/compiler.rb', line 95

def initialize(name:, filename: '<main>', span: Span::ZERO)
  @name = name
  @span = span
  @bytecode = BytecodeFunction.new(name:, filename:, span:) #: BytecodeFunction
  @last_local_index = -1 #: Integer
  @predefined_locals = 1 #: Integer
  @errors = [] #: Array[String]
  @locals = {} #: Hash[String, Integer]

  # reserve a slot for `self`
  define_local('#self')
end

Instance Attribute Details

#bytecodeObject (readonly)

: BytecodeFunction



80
81
82
# File 'lib/miniruby/compiler.rb', line 80

def bytecode
  @bytecode
end

#errorsObject (readonly)

: Array



89
90
91
# File 'lib/miniruby/compiler.rb', line 89

def errors
  @errors
end

#last_local_indexObject (readonly)

: Integer



86
87
88
# File 'lib/miniruby/compiler.rb', line 86

def last_local_index
  @last_local_index
end

#localsObject (readonly)

: Hash[String, Integer]



92
93
94
# File 'lib/miniruby/compiler.rb', line 92

def locals
  @locals
end

#nameObject (readonly)

: String



77
78
79
# File 'lib/miniruby/compiler.rb', line 77

def name
  @name
end

#predefined_localsObject (readonly)

: Integer



83
84
85
# File 'lib/miniruby/compiler.rb', line 83

def predefined_locals
  @predefined_locals
end

Class Method Details

.compile_ast(node, name: '<main>', filename: '<main>', span: Span::ZERO) ⇒ Object

Compile an AST node. : (AST::ProgramNode node, ?name: String, ?filename: String, ?span: Span) -> BytecodeFunction

Raises:



53
54
55
56
57
58
59
# File 'lib/miniruby/compiler.rb', line 53

def compile_ast(node, name: '<main>', filename: '<main>', span: Span::ZERO)
  compiler = new(name:, filename:, span:)
  compiler.compile_program(node)
  raise Error.new(compiler.errors) if compiler.err?

  compiler.bytecode
end

.compile_source(source, name: '<main>', filename: '<main>') ⇒ Object

Compile source code. : (String source, ?name: String, ?filename: String) -> BytecodeFunction

Raises:



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/miniruby/compiler.rb', line 63

def compile_source(source, name: '<main>', filename: '<main>')
  result = Parser.parse(source)
  raise Error.new(result.errors) if result.err?

  node = result.ast
  compiler = new(name:, filename:, span: node.span)
  compiler.compile_program(node)
  raise Error.new(compiler.errors) if compiler.err?

  compiler.bytecode
end

Instance Method Details

#compile_program(node) ⇒ Object

: (AST::ProgramNode node) -> void



109
110
111
112
113
# File 'lib/miniruby/compiler.rb', line 109

def compile_program(node)
  compile_statements(node.statements)
  emit(Opcode::RETURN)
  prepare_locals
end

#err?Boolean

: -> bool

Returns:

  • (Boolean)


116
117
118
# File 'lib/miniruby/compiler.rb', line 116

def err?
  @errors.length > 0
end