-
Notifications
You must be signed in to change notification settings - Fork 0
Extract compiler assembly emitter #61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
9343931
Extract compiler assembly emitter
katsyoshi a68b086
Extract compiler context
katsyoshi 5c6b07f
Extract compiler analyzer
katsyoshi c8584d4
Extract compiler variables context
katsyoshi ecee1d9
Add compiler function context
katsyoshi 7062e58
Add compiler entry context
katsyoshi 8c789cf
Track compiler functions
katsyoshi 67f5e5c
Generate methods from compiler functions
katsyoshi 79656d5
Support method-local variables
katsyoshi fb95d74
Preserve method conditional control flow
katsyoshi 81bb367
Reject unsupported method argument counts
katsyoshi 8c60bac
Preserve local assignment results
katsyoshi 65e012e
Reject unsupported method parameters
katsyoshi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| require_relative "context" | ||
|
|
||
| module Caotral | ||
| class Compiler | ||
| class Analyzer | ||
| def self.analyze(ast, context = Caotral::Compiler::Context.new) | ||
| new(ast, context).analyze | ||
| end | ||
|
|
||
| def initialize(ast, context) | ||
| @ast = ast | ||
| @context = context | ||
| end | ||
|
|
||
| def analyze | ||
| register_entry(@ast) | ||
| register_variables_and_methods(@ast) | ||
| @context | ||
| end | ||
|
|
||
| private | ||
| def register_variables_and_methods(node) | ||
| return unless node.kind_of?(RubyVM::AbstractSyntaxTree::Node) | ||
| type = node.type | ||
| variables, *_ = node.children | ||
| case type | ||
| when :SCOPE | ||
| variables.each { |v| @context.register_local_variable(v) } | ||
| when :DEFN | ||
| @context.discover_method(variables) | ||
| function = Caotral::Compiler::Context::Function.new(**analyze_function_scope(node)) | ||
| @context.register_function(function) | ||
| end | ||
| node.children.each { |n| register_variables_and_methods(n) } | ||
| nil | ||
| end | ||
|
|
||
| def register_entry(scope) | ||
| locals, _args, body = scope.children | ||
| entry = Caotral::Compiler::Context::Function.new(name: nil, locals:, body:) | ||
| @context.register_entry(entry) | ||
| end | ||
|
|
||
| def analyze_function_scope(node) | ||
| name, function_scope = node.children | ||
| locals, args, body = function_scope.children | ||
| parameter_count = args.children.first | ||
| parameters = locals.take(parameter_count) | ||
| locals = locals.drop(parameter_count) | ||
| { name:, parameters:, locals:, body: } | ||
| end | ||
| end | ||
| end | ||
| end | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| require_relative "context/function" | ||
| require_relative "context/variables" | ||
|
|
||
| module Caotral | ||
| class Compiler | ||
| class Context | ||
| attr_reader :discovered_methods, :label_sequence, :entry, :functions | ||
| def initialize | ||
| @label_sequence = 0 | ||
| @entry_emitted = false | ||
| @emitted_methods = Set[] | ||
| @discovered_methods = Set[] | ||
| @entry = nil | ||
| @variables = Caotral::Compiler::Context::Variables.new | ||
| @functions = {} | ||
| end | ||
|
|
||
| def entry_emitted? = @entry_emitted | ||
| def mark_entry_emitted = @entry_emitted = true | ||
| def mark_method_emitted(name) = @emitted_methods << name | ||
| def discover_method(name) = @discovered_methods << name | ||
| def register_local_variable(name) = @variables.register_local(name) | ||
| def all_methods_emitted? = @discovered_methods == @emitted_methods | ||
| def increment_label_sequence = @label_sequence += 1 | ||
| def local_variables = @variables.locals | ||
| def register_entry(function) = @entry = function | ||
| def register_function(function) = @functions[function.name] = function | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| require_relative "variables" | ||
|
|
||
| module Caotral | ||
| class Compiler | ||
| class Context | ||
| class Function | ||
| attr_reader :name, :parameters, :body | ||
| def initialize(name:, parameters: [], locals: [], body:) | ||
| @name = name | ||
| @parameters = parameters | ||
| @variables = Caotral::Compiler::Context::Variables.new | ||
| locals.each { |name| @variables.register_local(name) } | ||
| @body = body | ||
| end | ||
|
|
||
| def locals = @variables.locals | ||
| def variables = parameters + locals.to_a | ||
| end | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| module Caotral | ||
| class Compiler | ||
| class Context | ||
| class Variables | ||
| attr_reader :locals | ||
| def initialize = @locals = Set[] | ||
| def register_local(name) = @locals.add?(name) | ||
| end | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| module Caotral | ||
| class Compiler | ||
| class Emitter | ||
| INDENT = " " * 2 | ||
| def initialize(io) = @io = io | ||
|
|
||
| def instruction(operation, *operands) | ||
| ops = operands.empty? ? "" : " #{operands.join(", ")}" | ||
| @io.puts("#{INDENT}#{operation}#{ops}") | ||
| end | ||
| def label(name) = @io.puts("#{name}:") | ||
| def directive(row) = @io.puts(row) | ||
| def close = @io.close | ||
| end | ||
| end | ||
| end |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.