carbon-compiler 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|