carbon-compiler 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitattributes +17 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +39 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +9 -0
- data/Vagrantfile +84 -0
- data/carbon-compiler.gemspec +28 -0
- data/lib/carbon/compiler.rb +20 -0
- data/lib/carbon/compiler/directive.rb +48 -0
- data/lib/carbon/compiler/directive/import.rb +17 -0
- data/lib/carbon/compiler/errors.rb +7 -0
- data/lib/carbon/compiler/location.rb +136 -0
- data/lib/carbon/compiler/metanostic.rb +123 -0
- data/lib/carbon/compiler/metanostic/defaults.rb +41 -0
- data/lib/carbon/compiler/metanostic/defaults.yml +138 -0
- data/lib/carbon/compiler/metanostic/diagnostic.rb +112 -0
- data/lib/carbon/compiler/metanostic/list.rb +109 -0
- data/lib/carbon/compiler/metanostic/mode.rb +162 -0
- data/lib/carbon/compiler/metanostic/state.rb +174 -0
- data/lib/carbon/compiler/metanostic/template.erb +11 -0
- data/lib/carbon/compiler/node.rb +18 -0
- data/lib/carbon/compiler/node/base.rb +213 -0
- data/lib/carbon/compiler/node/definition.rb +19 -0
- data/lib/carbon/compiler/node/definition/class.rb +24 -0
- data/lib/carbon/compiler/node/definition/class/element.rb +18 -0
- data/lib/carbon/compiler/node/definition/directive.rb +22 -0
- data/lib/carbon/compiler/node/definition/directive/function.rb +18 -0
- data/lib/carbon/compiler/node/definition/enum.rb +20 -0
- data/lib/carbon/compiler/node/definition/enum/element.rb +17 -0
- data/lib/carbon/compiler/node/definition/function.rb +44 -0
- data/lib/carbon/compiler/node/definition/function/body.rb +17 -0
- data/lib/carbon/compiler/node/definition/function/name.rb +18 -0
- data/lib/carbon/compiler/node/definition/function/parameter.rb +18 -0
- data/lib/carbon/compiler/node/definition/function/parameters.rb +17 -0
- data/lib/carbon/compiler/node/definition/module.rb +23 -0
- data/lib/carbon/compiler/node/definition/struct.rb +24 -0
- data/lib/carbon/compiler/node/definition/struct/element.rb +18 -0
- data/lib/carbon/compiler/node/etype.rb +66 -0
- data/lib/carbon/compiler/node/etype/option.rb +25 -0
- data/lib/carbon/compiler/node/etype/star.rb +13 -0
- data/lib/carbon/compiler/node/expression.rb +18 -0
- data/lib/carbon/compiler/node/expression/assignment.rb +22 -0
- data/lib/carbon/compiler/node/expression/call.rb +22 -0
- data/lib/carbon/compiler/node/expression/call/access.rb +24 -0
- data/lib/carbon/compiler/node/expression/call/attribute.rb +23 -0
- data/lib/carbon/compiler/node/expression/call/enum.rb +25 -0
- data/lib/carbon/compiler/node/expression/call/module.rb +24 -0
- data/lib/carbon/compiler/node/expression/call/parameters.rb +17 -0
- data/lib/carbon/compiler/node/expression/call/self.rb +17 -0
- data/lib/carbon/compiler/node/expression/call/unified.rb +27 -0
- data/lib/carbon/compiler/node/expression/literal.rb +83 -0
- data/lib/carbon/compiler/node/expression/operation.rb +20 -0
- data/lib/carbon/compiler/node/expression/operation/and.rb +20 -0
- data/lib/carbon/compiler/node/expression/operation/neq.rb +21 -0
- data/lib/carbon/compiler/node/expression/operation/normal.rb +20 -0
- data/lib/carbon/compiler/node/expression/operation/or.rb +20 -0
- data/lib/carbon/compiler/node/expression/unit.rb +16 -0
- data/lib/carbon/compiler/node/name.rb +27 -0
- data/lib/carbon/compiler/node/root.rb +23 -0
- data/lib/carbon/compiler/node/statement.rb +24 -0
- data/lib/carbon/compiler/node/statement/catch.rb +20 -0
- data/lib/carbon/compiler/node/statement/condition.rb +14 -0
- data/lib/carbon/compiler/node/statement/else.rb +17 -0
- data/lib/carbon/compiler/node/statement/elsif.rb +18 -0
- data/lib/carbon/compiler/node/statement/finally.rb +17 -0
- data/lib/carbon/compiler/node/statement/for.rb +18 -0
- data/lib/carbon/compiler/node/statement/if.rb +18 -0
- data/lib/carbon/compiler/node/statement/let.rb +18 -0
- data/lib/carbon/compiler/node/statement/match.rb +14 -0
- data/lib/carbon/compiler/node/statement/return.rb +17 -0
- data/lib/carbon/compiler/node/statement/try.rb +19 -0
- data/lib/carbon/compiler/node/statement/while.rb +19 -0
- data/lib/carbon/compiler/parser.rb +63 -0
- data/lib/carbon/compiler/parser/common.rb +79 -0
- data/lib/carbon/compiler/parser/expressions.rb +39 -0
- data/lib/carbon/compiler/parser/expressions/precedence.rb +134 -0
- data/lib/carbon/compiler/parser/expressions/primary.rb +120 -0
- data/lib/carbon/compiler/parser/firsts.rb +74 -0
- data/lib/carbon/compiler/parser/helpers.rb +61 -0
- data/lib/carbon/compiler/parser/root.rb +57 -0
- data/lib/carbon/compiler/parser/root/class.rb +34 -0
- data/lib/carbon/compiler/parser/root/directive.rb +87 -0
- data/lib/carbon/compiler/parser/root/enum.rb +45 -0
- data/lib/carbon/compiler/parser/root/function.rb +90 -0
- data/lib/carbon/compiler/parser/root/struct.rb +34 -0
- data/lib/carbon/compiler/parser/root/trait.rb +44 -0
- data/lib/carbon/compiler/parser/statements.rb +86 -0
- data/lib/carbon/compiler/parser/statements/if.rb +50 -0
- data/lib/carbon/compiler/parser/statements/match.rb +39 -0
- data/lib/carbon/compiler/parser/statements/try.rb +49 -0
- data/lib/carbon/compiler/project.rb +37 -0
- data/lib/carbon/compiler/project/file.rb +64 -0
- data/lib/carbon/compiler/scanner.rb +82 -0
- data/lib/carbon/compiler/scanner/main.rb +76 -0
- data/lib/carbon/compiler/scanner/token.rb +58 -0
- data/lib/carbon/compiler/version.rb +8 -0
- data/lib/carbon/compiler/visitor.rb +13 -0
- data/lib/carbon/compiler/visitor/base.rb +52 -0
- data/lib/carbon/compiler/visitor/generation.rb +45 -0
- data/lib/carbon/compiler/visitor/generation/asserts.rb +30 -0
- data/lib/carbon/compiler/visitor/generation/class.rb +93 -0
- data/lib/carbon/compiler/visitor/generation/context.rb +75 -0
- data/lib/carbon/compiler/visitor/generation/expressions.rb +82 -0
- data/lib/carbon/compiler/visitor/generation/expressions/assignment.rb +105 -0
- data/lib/carbon/compiler/visitor/generation/expressions/calls.rb +89 -0
- data/lib/carbon/compiler/visitor/generation/function.rb +68 -0
- data/lib/carbon/compiler/visitor/generation/statements.rb +131 -0
- data/lib/carbon/compiler/visitor/generation/struct.rb +115 -0
- data/lib/carbon/compiler/visitor/preparation.rb +86 -0
- data/lib/carbon/compiler/visitor/preparation/expressions.rb +26 -0
- data/lib/carbon/compiler/visitor/preparation/function.rb +55 -0
- data/lib/carbon/compiler/visitor/preparation/statements.rb +73 -0
- data/lib/carbon/compiler/visitor/preparation/struct.rb +37 -0
- data/program.ca +16 -0
- data/test.rb +21 -0
- metadata +234 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
# The root node. This is the topmost level node, and includes
|
8
|
+
# all declarations, definitions, and directives.
|
9
|
+
class Name < Base
|
10
|
+
# The value of the name. This is a string representation of the
|
11
|
+
# name.
|
12
|
+
#
|
13
|
+
# @return [::String]
|
14
|
+
def value
|
15
|
+
@children[0].value
|
16
|
+
end
|
17
|
+
|
18
|
+
# Fancy inspection.
|
19
|
+
#
|
20
|
+
# @return [::String]
|
21
|
+
def inspect
|
22
|
+
"#(Name #{value})"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
# The root node. This is the topmost level node, and includes
|
8
|
+
# all declarations, definitions, and directives.
|
9
|
+
class Root < Base
|
10
|
+
# The "name" of the root.
|
11
|
+
#
|
12
|
+
# @return [Carbon::Concrete::Type]
|
13
|
+
def name
|
14
|
+
@children.select(&:identity?).last[0]
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect
|
18
|
+
"#[Module #{name.inspect}]"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "carbon/compiler/node/statement/catch"
|
5
|
+
require "carbon/compiler/node/statement/else"
|
6
|
+
require "carbon/compiler/node/statement/elsif"
|
7
|
+
require "carbon/compiler/node/statement/finally"
|
8
|
+
require "carbon/compiler/node/statement/for"
|
9
|
+
require "carbon/compiler/node/statement/if"
|
10
|
+
require "carbon/compiler/node/statement/let"
|
11
|
+
require "carbon/compiler/node/statement/match"
|
12
|
+
require "carbon/compiler/node/statement/return"
|
13
|
+
require "carbon/compiler/node/statement/try"
|
14
|
+
require "carbon/compiler/node/statement/while"
|
15
|
+
|
16
|
+
module Carbon
|
17
|
+
module Compiler
|
18
|
+
module Node
|
19
|
+
# A statement.
|
20
|
+
module Statement
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
module Statement
|
8
|
+
# A "catch" statement. This is used in try/catch/finally for
|
9
|
+
# exception handling.
|
10
|
+
# This has four children: the name of the variable to localize,
|
11
|
+
# the "klass" (type) of the variable, the body of the catch statement,
|
12
|
+
# and the following catch/finally statement. This takes the form of
|
13
|
+
# `catch <Name>:<Type> <Body> <Follow>`.
|
14
|
+
class Catch < Base
|
15
|
+
attributes name: 0, type: 1, body: 2, follow: 3
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
module Statement
|
8
|
+
# An else statement. This is used in the if/elsif/else construct
|
9
|
+
# to handle control flow. This has one child: the body of the else
|
10
|
+
# statement. This has the form of `else <Body>`.
|
11
|
+
class Else < Base
|
12
|
+
attribute body: 0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
module Statement
|
8
|
+
# An elsif statement. This is used in the if/elsif/else construct
|
9
|
+
# for control flow. This has three children: the condition for
|
10
|
+
# execution, the body for execution, and the following elsif/else
|
11
|
+
# statement. This has the form `elsif(<Condition>) <Body> <Follow>`.
|
12
|
+
class ElsIf < Base
|
13
|
+
attributes condition: 0, body: 1, follow: 2
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
module Statement
|
8
|
+
# A Finally statement. This is used in try/catch/finally constructs
|
9
|
+
# for exception handling. This has one child: the body to execute.
|
10
|
+
# This takes the form of `finally <Body>`.
|
11
|
+
class Finally < Base
|
12
|
+
attributes body: 0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
module Statement
|
8
|
+
# A for loop. This is used to construct a loop with the given
|
9
|
+
# conditions. This has four children: the initial statement, the
|
10
|
+
# condition, the increment statement, and the body. This takes the
|
11
|
+
# form of `for(<Initial>; <Condition>; <Increment>) <Body>`.
|
12
|
+
class For < Base
|
13
|
+
attributes initial: 0, condition: 1, increment: 2, body: 3
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
module Statement
|
8
|
+
# An If statement. This is used in the if/elsif/else construct for
|
9
|
+
# control flow. This has three children: the children, the body,
|
10
|
+
# and the following elsif/else statement. This takes the form
|
11
|
+
# `if(<Condition>) <Body> <Follow>`.
|
12
|
+
class If < Base
|
13
|
+
attributes condition: 0, body: 1, follow: 2
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
module Statement
|
8
|
+
# A let statement. This introduces a local variable with a given
|
9
|
+
# "klass" (type). This has three children: the name of the local
|
10
|
+
# variable, the "klass" (type) of the local variable, and the given
|
11
|
+
# value of the new variable.
|
12
|
+
class Let < Base
|
13
|
+
attributes name: 0, type: 1, value: 2
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
module Statement
|
8
|
+
# A return statement. This is used for control flow to return from the
|
9
|
+
# current function. This has one child: the value to return. If no
|
10
|
+
# value is given, it returns a void type.
|
11
|
+
class Return < Base
|
12
|
+
attributes value: 0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
module Statement
|
8
|
+
# A "try" statement. This is used in try/catch/finally for
|
9
|
+
# exception handling.
|
10
|
+
# This has two children: the body to attempt to execute, and the
|
11
|
+
# following catch/finally block. This takes the form of
|
12
|
+
# `try <Body> <Follow>`.
|
13
|
+
class Try < Base
|
14
|
+
attributes body: 0, follow: 1
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
module Node
|
7
|
+
module Statement
|
8
|
+
# A while loop. This creates a loop that executes while a given
|
9
|
+
# condition is true.
|
10
|
+
# This has two children: the condition to check for truthiness, and
|
11
|
+
# the body to execute. This takes the form of
|
12
|
+
# `while(<Condition>) <Body>`.
|
13
|
+
class While < Base
|
14
|
+
attributes condition: 0, body: 1
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "carbon/compiler/parser/firsts"
|
5
|
+
require "carbon/compiler/parser/helpers"
|
6
|
+
require "carbon/compiler/parser/common"
|
7
|
+
require "carbon/compiler/parser/root"
|
8
|
+
require "carbon/compiler/parser/statements"
|
9
|
+
require "carbon/compiler/parser/expressions"
|
10
|
+
|
11
|
+
module Carbon
|
12
|
+
module Compiler
|
13
|
+
# The parser. This takes a series of tokens, generated by the {Scanner},
|
14
|
+
# and derives structure from these tokens. This makes the fundamental
|
15
|
+
# bases of creating a concrete representation of what is in the file.
|
16
|
+
class Parser
|
17
|
+
include Parser::Helpers
|
18
|
+
include Parser::Common
|
19
|
+
include Parser::Root
|
20
|
+
include Parser::Statements
|
21
|
+
include Parser::Expressions
|
22
|
+
|
23
|
+
# The scanner that acts as the source of the tokens.
|
24
|
+
#
|
25
|
+
# @return [Scanner]
|
26
|
+
attr_reader :scanner
|
27
|
+
|
28
|
+
# Initialize the parser. It takes a scanner, and the project that
|
29
|
+
# the parser is a part of.
|
30
|
+
#
|
31
|
+
# @param scanner [Scanner]
|
32
|
+
# @param project [Project]
|
33
|
+
def initialize(scanner)
|
34
|
+
@scanner = scanner
|
35
|
+
@file = @scanner.file
|
36
|
+
@enum = @scanner.each
|
37
|
+
end
|
38
|
+
|
39
|
+
# Pretty inspect.
|
40
|
+
#
|
41
|
+
# @return [String]
|
42
|
+
def inspect
|
43
|
+
"#<#{self.class} #{@scanner.file.name}>"
|
44
|
+
end
|
45
|
+
|
46
|
+
# Parses the input. This is cached to prevent multiple runs.
|
47
|
+
#
|
48
|
+
# @return [Parser::Node]
|
49
|
+
def parse
|
50
|
+
@_root ||= parse_root
|
51
|
+
end
|
52
|
+
alias_method :root, :parse
|
53
|
+
|
54
|
+
# Destroys the cache for {#parse}, allowing the parsing to occur again.
|
55
|
+
#
|
56
|
+
# @return [void]
|
57
|
+
def clear!
|
58
|
+
@enum.reset
|
59
|
+
@_root = nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Carbon
|
5
|
+
module Compiler
|
6
|
+
class Parser
|
7
|
+
# Parses common items, such as module names and types.
|
8
|
+
module Common
|
9
|
+
protected
|
10
|
+
|
11
|
+
Parser.first(:name, [:IDENTIFIER, :module, :struct, :enum, :trait,
|
12
|
+
:def, :self, :_])
|
13
|
+
def parse_name
|
14
|
+
error(first(:name)) unless first(:name).include?(peek.type)
|
15
|
+
Node::Name.new([shift])
|
16
|
+
end
|
17
|
+
|
18
|
+
# TODO: pointer
|
19
|
+
Parser.first(:type, [:MNAME, :"("])
|
20
|
+
def parse_type
|
21
|
+
type =
|
22
|
+
case peek.type
|
23
|
+
when :MNAME then parse_module_name
|
24
|
+
when :"(" then parse_unit_type
|
25
|
+
else error first(:type)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse_unit_type
|
30
|
+
expect :"("
|
31
|
+
children = []
|
32
|
+
until peek? :")"
|
33
|
+
children << parse_type
|
34
|
+
break unless peek? :","
|
35
|
+
expect :","
|
36
|
+
end
|
37
|
+
expect :")"
|
38
|
+
|
39
|
+
Node::Type::Unit.new(children)
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_module_name
|
43
|
+
base = parse_module_name_part
|
44
|
+
children = [base]
|
45
|
+
while peek? :"::"
|
46
|
+
expect :"::"
|
47
|
+
children << parse_module_name_part
|
48
|
+
end
|
49
|
+
|
50
|
+
location = children.map(&:location).inject(:|)
|
51
|
+
Concrete::Type.new(Concrete::Type::Name.new(children, nil),
|
52
|
+
location: location)
|
53
|
+
end
|
54
|
+
|
55
|
+
def parse_module_name_part
|
56
|
+
root = expect :MNAME
|
57
|
+
generics = peek?(:<) ? parse_module_generics : []
|
58
|
+
location = [root].concat(generics).map(&:location).inject(:|)
|
59
|
+
Concrete::Type::Part.new(root.value, generics, location: location)
|
60
|
+
end
|
61
|
+
|
62
|
+
def parse_module_generics
|
63
|
+
children = []
|
64
|
+
expect :<
|
65
|
+
until peek? :>
|
66
|
+
name = parse_module_name
|
67
|
+
children << Concrete::Type::Generic.new(name, [],
|
68
|
+
location: name.location)
|
69
|
+
break unless peek? :","
|
70
|
+
expect :","
|
71
|
+
end
|
72
|
+
expect :>
|
73
|
+
|
74
|
+
children
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|