mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 07:24:42 +01:00
executable semantics/syntax: move to a subpackage.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
# Exceptions. See /LICENSE for license information.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
# TODO(https://github.com/carbon-language/carbon-lang/issues/266):
|
||||
# Migrate bison/flex usage to a more hermetic bazel build.
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
|
||||
|
||||
package(default_visibility = ["//executable_semantics:__subpackages__"])
|
||||
|
||||
cc_library(
|
||||
name = "syntax",
|
||||
srcs = [
|
||||
"syntax.tab.cpp",
|
||||
"syntax.yy.cpp",
|
||||
"syntax_helpers.cpp",
|
||||
"syntax_helpers.h",
|
||||
],
|
||||
hdrs = ["syntax.tab.h"],
|
||||
# Disable warnings for generated code.
|
||||
copts = [
|
||||
"-Wno-unneeded-internal-declaration",
|
||||
"-Wno-unused-function",
|
||||
"-Wno-writable-strings",
|
||||
],
|
||||
deps = [
|
||||
"//executable_semantics:tracing_flag",
|
||||
"//executable_semantics/ast:declaration",
|
||||
"//executable_semantics/ast:expression",
|
||||
"//executable_semantics/ast:field_list",
|
||||
"//executable_semantics/interpreter",
|
||||
],
|
||||
)
|
||||
|
||||
genrule(
|
||||
name = "syntax_bison_srcs",
|
||||
srcs = ["syntax.ypp"],
|
||||
outs = [
|
||||
"syntax.tab.cpp",
|
||||
"syntax.tab.h",
|
||||
],
|
||||
cmd = "M4=$(M4) $(BISON) " +
|
||||
"--output=$(location syntax.tab.cpp) " +
|
||||
"--defines=$(location syntax.tab.h) " +
|
||||
"$(location syntax.ypp)",
|
||||
toolchains = [
|
||||
"@rules_bison//bison:current_bison_toolchain",
|
||||
"@rules_m4//m4:current_m4_toolchain",
|
||||
],
|
||||
)
|
||||
|
||||
genrule(
|
||||
name = "syntax_flex_srcs",
|
||||
srcs = ["syntax.lpp"],
|
||||
outs = ["syntax.yy.cpp"],
|
||||
cmd = "M4=$(M4) $(FLEX) " +
|
||||
"--outfile=$(location syntax.yy.cpp) " +
|
||||
"$(location syntax.lpp)",
|
||||
toolchains = [
|
||||
"@rules_flex//flex:current_flex_toolchain",
|
||||
"@rules_m4//m4:current_m4_toolchain",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
Exceptions. See /LICENSE for license information.
|
||||
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
%{
|
||||
#include <cstdlib>
|
||||
#include "executable_semantics/syntax/syntax.tab.h"
|
||||
%}
|
||||
|
||||
/* Turn off legacy bits we don't need */
|
||||
%option noyywrap nounput nodefault noinput
|
||||
|
||||
/* maintains the number of the current line read from input in the
|
||||
global variable yylineno.
|
||||
*/
|
||||
%option yylineno
|
||||
|
||||
AND "and"
|
||||
ARROW "->"
|
||||
AUTO "auto"
|
||||
BOOL "Bool"
|
||||
BREAK "break"
|
||||
CASE "case"
|
||||
CHOICE "choice"
|
||||
COMMENT \/\/[^\n]*\n
|
||||
CONTINUE "continue"
|
||||
DBLARROW "=>"
|
||||
DEFAULT "default"
|
||||
ELSE "else"
|
||||
EQUAL "=="
|
||||
FALSE "false"
|
||||
FN "fn"
|
||||
FNTY "fnty"
|
||||
IF "if"
|
||||
INT "Int"
|
||||
MATCH "match"
|
||||
NOT "not"
|
||||
OR "or"
|
||||
RETURN "return"
|
||||
STRUCT "struct"
|
||||
TRUE "true"
|
||||
TYPE "Type"
|
||||
VAR "var"
|
||||
WHILE "while"
|
||||
|
||||
identifier [A-Za-z_][A-Za-z0-9_]*
|
||||
integer_literal [0-9]+
|
||||
|
||||
%%
|
||||
|
||||
{AND} { return AND; }
|
||||
{ARROW} { return ARROW; }
|
||||
{AUTO} { return AUTO; }
|
||||
{BOOL} { return BOOL; }
|
||||
{BREAK} { return BREAK; }
|
||||
{CASE} { return CASE; }
|
||||
{CHOICE} { return CHOICE; }
|
||||
{COMMENT} ;
|
||||
{CONTINUE} { return CONTINUE; }
|
||||
{DBLARROW} { return DBLARROW; }
|
||||
{DEFAULT} { return DEFAULT; }
|
||||
{ELSE} { return ELSE; }
|
||||
{EQUAL} { return EQUAL; }
|
||||
{FALSE} { return FALSE; }
|
||||
{FN} { return FN; }
|
||||
{FNTY} { return FNTY; }
|
||||
{IF} { return IF; }
|
||||
{INT} { return INT; }
|
||||
{MATCH} { return MATCH; }
|
||||
{NOT} { return NOT; }
|
||||
{OR} { return OR; }
|
||||
{RETURN} { return RETURN; }
|
||||
{STRUCT} { return STRUCT; }
|
||||
{TRUE} { return TRUE; }
|
||||
{TYPE} { return TYPE; }
|
||||
{VAR} { return VAR; }
|
||||
{WHILE} { return WHILE; }
|
||||
|
||||
{identifier} {
|
||||
int n = strlen(yytext);
|
||||
yylval.str = reinterpret_cast<char*>(malloc((n + 1) * sizeof(char)));
|
||||
strncpy(yylval.str, yytext, n + 1);
|
||||
return identifier;
|
||||
}
|
||||
{integer_literal} {
|
||||
yylval.num = atof(yytext);
|
||||
return integer_literal;
|
||||
}
|
||||
|
||||
[ \t\n]+ ;
|
||||
. { return yytext[0]; }
|
||||
|
||||
%%
|
||||
@@ -0,0 +1,340 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
%code top {
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
#include "executable_semantics/syntax/syntax_helpers.h"
|
||||
}
|
||||
|
||||
%code requires {
|
||||
#include "executable_semantics/ast/declaration.h"
|
||||
#include "executable_semantics/ast/field_list.h"
|
||||
#include "executable_semantics/ast/function_definition.h"
|
||||
}
|
||||
|
||||
%code {
|
||||
extern int yylineno;
|
||||
extern int yylex();
|
||||
|
||||
void yyerror(char* error) {
|
||||
Carbon::PrintSyntaxError(error, yylineno);
|
||||
}
|
||||
// void yyerror(char* error, ...);
|
||||
}
|
||||
|
||||
%union {
|
||||
char* str;
|
||||
int num;
|
||||
Carbon::Expression* expression;
|
||||
std::list<std::pair<std::string, Carbon::Expression*>>* field_types;
|
||||
Carbon::Statement* statement;
|
||||
Carbon::Statement* statement_list;
|
||||
Carbon::FunctionDefinition* function_definition;
|
||||
Carbon::Declaration* declaration;
|
||||
std::list<Carbon::Declaration>* declaration_list;
|
||||
Carbon::Member* member;
|
||||
std::list<Carbon::Member*>* member_list;
|
||||
Carbon::FieldList* field_list;
|
||||
std::pair<std::string, Carbon::Expression*>* alternative;
|
||||
std::list<std::pair<std::string, Carbon::Expression*>>* alternative_list;
|
||||
std::pair<Carbon::Expression*, Carbon::Statement*>* clause;
|
||||
std::list<std::pair<Carbon::Expression*, Carbon::Statement*>>* clause_list;
|
||||
Carbon::Expression* fun_type;
|
||||
};
|
||||
|
||||
%token <num> integer_literal
|
||||
%token <str> identifier
|
||||
%type <str> designator
|
||||
%type <declaration> declaration
|
||||
%type <function_definition> function_declaration
|
||||
%type <function_definition> function_definition
|
||||
%type <declaration_list> declaration_list
|
||||
%type <statement> statement
|
||||
%type <statement> optional_else
|
||||
%type <statement_list> statement_list
|
||||
%type <expression> expression
|
||||
%type <expression> pattern
|
||||
%type <expression> return_type
|
||||
%type <expression> paren_expression
|
||||
%type <expression> tuple
|
||||
%type <member> member
|
||||
%type <member_list> member_list
|
||||
%type <field_list> field
|
||||
%type <field_list> field_list
|
||||
%type <alternative> alternative
|
||||
%type <alternative_list> alternative_list
|
||||
%type <clause> clause
|
||||
%type <clause_list> clause_list
|
||||
%token AND
|
||||
%token OR
|
||||
%token NOT
|
||||
%token INT
|
||||
%token BOOL
|
||||
%token TYPE
|
||||
%token FN
|
||||
%token FNTY
|
||||
%token ARROW
|
||||
%token VAR
|
||||
%token EQUAL
|
||||
%token IF
|
||||
%token ELSE
|
||||
%token WHILE
|
||||
%token BREAK
|
||||
%token CONTINUE
|
||||
%token RETURN
|
||||
%token TRUE
|
||||
%token FALSE
|
||||
%token STRUCT
|
||||
%token CHOICE
|
||||
%token MATCH
|
||||
%token CASE
|
||||
%token DBLARROW
|
||||
%token DEFAULT
|
||||
%token AUTO
|
||||
%nonassoc '{' '}'
|
||||
%nonassoc ':' ',' DBLARROW
|
||||
%left OR AND
|
||||
%nonassoc EQUAL NOT
|
||||
%left '+' '-'
|
||||
%left '.' ARROW
|
||||
%nonassoc '(' ')' '[' ']'
|
||||
%start input
|
||||
%locations
|
||||
%%
|
||||
input: declaration_list
|
||||
{ Carbon::ExecProgram($1); }
|
||||
;
|
||||
pattern:
|
||||
expression
|
||||
{ $$ = $1; }
|
||||
;
|
||||
expression:
|
||||
identifier
|
||||
{ $$ = Carbon::MakeVar(yylineno, $1); }
|
||||
| expression designator
|
||||
{ $$ = Carbon::MakeGetField(yylineno, $1, $2); }
|
||||
| expression '[' expression ']'
|
||||
{ $$ = Carbon::MakeIndex(yylineno, $1, $3); }
|
||||
| expression ':' identifier
|
||||
{ $$ = Carbon::MakeVarPat(yylineno, $3, $1); }
|
||||
| integer_literal
|
||||
{ $$ = Carbon::MakeInt(yylineno, $1); }
|
||||
| TRUE
|
||||
{ $$ = Carbon::MakeBool(yylineno, true); }
|
||||
| FALSE
|
||||
{ $$ = Carbon::MakeBool(yylineno, false); }
|
||||
| INT
|
||||
{ $$ = Carbon::MakeIntType(yylineno); }
|
||||
| BOOL
|
||||
{ $$ = Carbon::MakeBoolType(yylineno); }
|
||||
| TYPE
|
||||
{ $$ = Carbon::MakeTypeType(yylineno); }
|
||||
| AUTO
|
||||
{ $$ = Carbon::MakeAutoType(yylineno); }
|
||||
| paren_expression { $$ = $1; }
|
||||
| expression EQUAL expression
|
||||
{ $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Eq, $1, $3); }
|
||||
| expression '+' expression
|
||||
{ $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Add, $1, $3); }
|
||||
| expression '-' expression
|
||||
{ $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Sub, $1, $3); }
|
||||
| expression AND expression
|
||||
{ $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::And, $1, $3); }
|
||||
| expression OR expression
|
||||
{ $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Or, $1, $3); }
|
||||
| NOT expression
|
||||
{ $$ = Carbon::MakeUnOp(yylineno, Carbon::Operator::Not, $2); }
|
||||
| '-' expression
|
||||
{ $$ = Carbon::MakeUnOp(yylineno, Carbon::Operator::Neg, $2); }
|
||||
| expression tuple
|
||||
{ $$ = Carbon::MakeCall(yylineno, $1, $2); }
|
||||
| FNTY tuple return_type
|
||||
{ $$ = Carbon::MakeFunType(yylineno, $2, $3); }
|
||||
;
|
||||
designator: '.' identifier { $$ = $2; }
|
||||
;
|
||||
paren_expression: '(' field_list ')'
|
||||
{
|
||||
if ($2->fields->size() == 1 &&
|
||||
$2->fields->front().first == "" &&
|
||||
!$2->has_explicit_comma) {
|
||||
$$ = $2->fields->front().second;
|
||||
} else {
|
||||
auto vec = new std::vector<std::pair<std::string,Carbon::Expression*>>(
|
||||
$2->fields->begin(), $2->fields->end());
|
||||
$$ = Carbon::MakeTuple(yylineno, vec);
|
||||
}
|
||||
}
|
||||
;
|
||||
tuple: '(' field_list ')'
|
||||
{
|
||||
auto vec = new std::vector<std::pair<std::string,Carbon::Expression*>>(
|
||||
$2->fields->begin(), $2->fields->end());
|
||||
$$ = Carbon::MakeTuple(yylineno, vec);
|
||||
}
|
||||
field:
|
||||
pattern
|
||||
{
|
||||
auto fields =
|
||||
new std::list<std::pair<std::string, Carbon::Expression*>>();
|
||||
fields->push_back(std::make_pair("", $1));
|
||||
$$ = Carbon::MakeFieldList(fields);
|
||||
}
|
||||
| designator '=' pattern
|
||||
{
|
||||
auto fields =
|
||||
new std::list<std::pair<std::string, Carbon::Expression*>>();
|
||||
fields->push_back(std::make_pair($1, $3));
|
||||
$$ = Carbon::MakeFieldList(fields);
|
||||
}
|
||||
;
|
||||
field_list:
|
||||
// Empty
|
||||
{
|
||||
$$ = Carbon::MakeFieldList(
|
||||
new std::list<std::pair<std::string, Carbon::Expression*>>());
|
||||
}
|
||||
| field
|
||||
{ $$ = $1; }
|
||||
| field ',' field_list
|
||||
{ $$ = Carbon::MakeConsField($1, $3); }
|
||||
;
|
||||
clause:
|
||||
CASE pattern DBLARROW statement
|
||||
{ $$ = new std::pair<Carbon::Expression*, Carbon::Statement*>($2, $4); }
|
||||
| DEFAULT DBLARROW statement
|
||||
{
|
||||
auto vp = Carbon::MakeVarPat(yylineno, "_",
|
||||
Carbon::MakeAutoType(yylineno));
|
||||
$$ = new std::pair<Carbon::Expression*, Carbon::Statement*>(vp, $3);
|
||||
}
|
||||
;
|
||||
clause_list:
|
||||
// Empty
|
||||
{
|
||||
$$ = new std::list<std::pair<Carbon::Expression*, Carbon::Statement*>>();
|
||||
}
|
||||
| clause clause_list
|
||||
{ $$ = $2; $$->push_front(*$1); }
|
||||
;
|
||||
statement:
|
||||
expression '=' expression ';'
|
||||
{ $$ = Carbon::MakeAssign(yylineno, $1, $3); }
|
||||
| VAR pattern '=' expression ';'
|
||||
{ $$ = Carbon::MakeVarDef(yylineno, $2, $4); }
|
||||
| expression ';'
|
||||
{ $$ = Carbon::MakeExpStmt(yylineno, $1); }
|
||||
| IF '(' expression ')' statement optional_else
|
||||
{ $$ = Carbon::MakeIf(yylineno, $3, $5, $6); }
|
||||
| WHILE '(' expression ')' statement
|
||||
{ $$ = Carbon::MakeWhile(yylineno, $3, $5); }
|
||||
| BREAK ';'
|
||||
{ $$ = Carbon::MakeBreak(yylineno); }
|
||||
| CONTINUE ';'
|
||||
{ $$ = Carbon::MakeContinue(yylineno); }
|
||||
| RETURN expression ';'
|
||||
{ $$ = Carbon::MakeReturn(yylineno, $2); }
|
||||
| '{' statement_list '}'
|
||||
{ $$ = Carbon::MakeBlock(yylineno, $2); }
|
||||
| MATCH '(' expression ')' '{' clause_list '}'
|
||||
{ $$ = Carbon::MakeMatch(yylineno, $3, $6); }
|
||||
;
|
||||
optional_else:
|
||||
// Empty
|
||||
{ $$ = 0; }
|
||||
| ELSE statement { $$ = $2; }
|
||||
;
|
||||
statement_list:
|
||||
// Empty
|
||||
{ $$ = 0; }
|
||||
| statement statement_list
|
||||
{ $$ = Carbon::MakeSeq(yylineno, $1, $2); }
|
||||
;
|
||||
return_type:
|
||||
// Empty
|
||||
{
|
||||
$$ = Carbon::MakeTuple(
|
||||
yylineno,
|
||||
new std::vector<std::pair<std::string, Carbon::Expression*>>());
|
||||
}
|
||||
| ARROW expression
|
||||
{ $$ = $2; }
|
||||
;
|
||||
function_definition:
|
||||
FN identifier tuple return_type '{' statement_list '}'
|
||||
{ $$ = MakeFunDef(yylineno, $2, $4, $3, $6); }
|
||||
| FN identifier tuple DBLARROW expression ';'
|
||||
{
|
||||
$$ = Carbon::MakeFunDef(yylineno, $2, Carbon::MakeAutoType(yylineno), $3,
|
||||
Carbon::MakeReturn(yylineno, $5));
|
||||
}
|
||||
;
|
||||
function_declaration:
|
||||
FN identifier tuple return_type ';'
|
||||
{ $$ = MakeFunDef(yylineno, $2, $4, $3, 0); }
|
||||
;
|
||||
member:
|
||||
VAR expression ':' identifier ';'
|
||||
{ $$ = MakeField(yylineno, $4, $2); }
|
||||
;
|
||||
member_list:
|
||||
// Empty
|
||||
{ $$ = new std::list<Carbon::Member*>(); }
|
||||
| member member_list
|
||||
{ $$ = $2; $$->push_front($1); }
|
||||
;
|
||||
alternative:
|
||||
identifier tuple
|
||||
{ $$ = new std::pair<std::string, Carbon::Expression*>($1, $2); }
|
||||
| identifier
|
||||
{
|
||||
$$ = new std::pair<std::string, Carbon::Expression*>(
|
||||
$1, Carbon::MakeTuple(
|
||||
yylineno,
|
||||
new std::vector<std::pair<std::string, Carbon::Expression*>>()));
|
||||
}
|
||||
;
|
||||
alternative_list:
|
||||
// Empty
|
||||
{ $$ = new std::list<std::pair<std::string, Carbon::Expression*>>(); }
|
||||
| alternative
|
||||
{
|
||||
$$ = new std::list<std::pair<std::string, Carbon::Expression*>>();
|
||||
$$->push_front(*$1);
|
||||
}
|
||||
| alternative ',' alternative_list
|
||||
{ $$ = $3; $$->push_front(*$1); }
|
||||
;
|
||||
declaration:
|
||||
function_definition
|
||||
{ $$ = new Carbon::Declaration(Carbon::FunctionDeclaration{$1}); }
|
||||
| function_declaration
|
||||
{ $$ = new Carbon::Declaration(Carbon::FunctionDeclaration{$1}); }
|
||||
| STRUCT identifier '{' member_list '}'
|
||||
{
|
||||
$$ = new Carbon::Declaration(
|
||||
Carbon::StructDeclaration{yylineno, $2, $4});
|
||||
}
|
||||
| CHOICE identifier '{' alternative_list '}'
|
||||
{
|
||||
$$ = new Carbon::Declaration(
|
||||
Carbon::ChoiceDeclaration{yylineno, $2, std::list(*$4)});
|
||||
}
|
||||
;
|
||||
declaration_list:
|
||||
// Empty
|
||||
{ $$ = new std::list<Carbon::Declaration>(); }
|
||||
| declaration declaration_list
|
||||
{
|
||||
$$ = $2;
|
||||
$$->push_front(*$1);
|
||||
}
|
||||
;
|
||||
%%
|
||||
@@ -0,0 +1,50 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include "executable_semantics/syntax/syntax_helpers.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "executable_semantics/interpreter/interpreter.h"
|
||||
#include "executable_semantics/interpreter/typecheck.h"
|
||||
#include "executable_semantics/tracing_flag.h"
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
const char* input_filename = nullptr;
|
||||
|
||||
void PrintSyntaxError(char* error, int line_num) {
|
||||
std::cerr << input_filename << ":" << line_num << ": " << error << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void ExecProgram(std::list<Declaration>* fs) {
|
||||
if (tracing_output) {
|
||||
std::cout << "********** source program **********" << std::endl;
|
||||
for (const auto& decl : *fs) {
|
||||
decl.Print();
|
||||
}
|
||||
std::cout << "********** type checking **********" << std::endl;
|
||||
}
|
||||
state = new State(); // Compile-time state.
|
||||
std::pair<TypeEnv*, Env*> p = TopLevel(fs);
|
||||
TypeEnv* top = p.first;
|
||||
Env* ct_top = p.second;
|
||||
std::list<Declaration> new_decls;
|
||||
for (const auto& decl : *fs) {
|
||||
new_decls.push_back(decl.TypeChecked(top, ct_top));
|
||||
}
|
||||
if (tracing_output) {
|
||||
std::cout << std::endl;
|
||||
std::cout << "********** type checking complete **********" << std::endl;
|
||||
for (const auto& decl : new_decls) {
|
||||
decl.Print();
|
||||
}
|
||||
std::cout << "********** starting execution **********" << std::endl;
|
||||
}
|
||||
int result = InterpProgram(&new_decls);
|
||||
std::cout << "result: " << result << std::endl;
|
||||
}
|
||||
|
||||
} // namespace Carbon
|
||||
@@ -0,0 +1,29 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Helpers should be added here when logic in syntax.ypp is more than a single
|
||||
// statement. The intent is to minimize the amount of C++ in the .ypp file, to
|
||||
// improve ease of maintenance.
|
||||
|
||||
#ifndef EXECUTABLE_SEMANTICS_EXEC_H_
|
||||
#define EXECUTABLE_SEMANTICS_EXEC_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "executable_semantics/ast/declaration.h"
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
// Initialized by main(), and used when printing errors.
|
||||
extern const char* input_filename;
|
||||
|
||||
// Prints errors.
|
||||
void PrintSyntaxError(char* error, int line_num);
|
||||
|
||||
// Runs the top-level declaration list.
|
||||
void ExecProgram(std::list<Declaration>* fs);
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
#endif // EXECUTABLE_SEMANTICS_EXEC_H_
|
||||
Reference in New Issue
Block a user