mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Work on getting typeof up and running. Try-else now works.
This commit is contained in:
40
.github/workflows/main2.yml
vendored
Normal file
40
.github/workflows/main2.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: CI
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the master branch
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "build"
|
||||
build:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Build & Test
|
||||
uses: ashutoshvarma/action-cmake-build@master
|
||||
with:
|
||||
build-dir: ${{ runner.workspace }}/build
|
||||
# will set the CC & CXX for cmake
|
||||
cc: gcc
|
||||
cxx: g++
|
||||
build-type: Release
|
||||
# Extra options pass to cmake while configuring project
|
||||
configure-options: -DCMAKE_C_FLAGS=-w32 -DPNG_INCLUDE=OFF
|
||||
run-test: true
|
||||
ctest-options: -R mytest
|
||||
# install the build using cmake --install
|
||||
install-build: true
|
||||
# run build using '-j [parallel]' to use multiple threads to build
|
||||
parallel: 14
|
||||
@@ -9,24 +9,25 @@ int yylex(void);
|
||||
void yyerror(char *s);
|
||||
%}
|
||||
|
||||
%token IDENT CT_IDENT CONSTANT CONST_IDENT TYPE_IDENT STRING_LITERAL SIZEOF
|
||||
%token IDENT CT_IDENT CT_TYPE_IDENT CONSTANT CT_CONST_IDENT CONST_IDENT TYPE_IDENT STRING_LITERAL SIZEOF
|
||||
%token INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
|
||||
%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
|
||||
%token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
|
||||
%token ADD_MOD SUB_MOD MULT_MOD ADD_MOD_ASSIGN SUB_MOD_ASSIGN
|
||||
%token MULT_MOD_ASSIGN NEG_MOD
|
||||
%token XOR_ASSIGN OR_ASSIGN VAR NIL ELVIS HASH_IDENT NEXT
|
||||
%token AT
|
||||
|
||||
%token TYPEDEF MODULE IMPORT
|
||||
%token CHAR SHORT INT LONG FLOAT DOUBLE CONST VOLATILE VOID
|
||||
%token BYTE USHORT UINT ULONG BOOL
|
||||
%token TYPEID
|
||||
%token STRUCT UNION ENUM ELLIPSIS AS LOCAL
|
||||
|
||||
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
|
||||
%token TYPE FUNC ERROR MACRO GENERIC CTIF CTELIF CTENDIF CTELSE CTSWITCH CTCASE CTDEFAULT CTFOR
|
||||
%token FUNC ERROR MACRO GENERIC CTIF CTELIF CTENDIF CTELSE CTSWITCH CTCASE CTDEFAULT CTFOR
|
||||
%token THROWS THROW TRY CATCH SCOPE PUBLIC DEFER ATTRIBUTE IN
|
||||
|
||||
%token FN_BLOCK_START FN_BLOCK_END
|
||||
%token MULTW ADDW SUBW
|
||||
%token AUTO
|
||||
|
||||
%start translation_unit
|
||||
@@ -46,6 +47,7 @@ ident_expression
|
||||
: CONST_IDENT
|
||||
| IDENT
|
||||
| CT_IDENT
|
||||
| CT_CONST_IDENT
|
||||
;
|
||||
|
||||
primary_expression
|
||||
@@ -55,8 +57,10 @@ primary_expression
|
||||
| path ident_expression
|
||||
| ident_expression
|
||||
| base_type initializer_list
|
||||
| base_type '.' IDENT
|
||||
| TYPE '(' type_expression ')'
|
||||
| type '.' IDENT
|
||||
| type '.' TYPEID
|
||||
| '(' type ')' '.' IDENT
|
||||
| '(' type ')' '.' TYPEID
|
||||
| '(' expression ')'
|
||||
| FN_BLOCK_START statement_list FN_BLOCK_END
|
||||
;
|
||||
@@ -81,7 +85,6 @@ unary_expression
|
||||
| INC_OP unary_expression
|
||||
| DEC_OP unary_expression
|
||||
| unary_operator unary_expression
|
||||
| SIZEOF '(' type_expression ')'
|
||||
;
|
||||
|
||||
unary_operator
|
||||
@@ -89,7 +92,7 @@ unary_operator
|
||||
| '*'
|
||||
| '+'
|
||||
| '-'
|
||||
| SUBW
|
||||
| NEG_MOD
|
||||
| '~'
|
||||
| '!'
|
||||
| '@'
|
||||
@@ -99,7 +102,7 @@ unary_operator
|
||||
multiplicative_expression
|
||||
: unary_expression
|
||||
| multiplicative_expression '*' unary_expression
|
||||
| multiplicative_expression MULTW unary_expression
|
||||
| multiplicative_expression MULT_MOD unary_expression
|
||||
| multiplicative_expression '/' unary_expression
|
||||
| multiplicative_expression '%' unary_expression
|
||||
;
|
||||
@@ -120,9 +123,9 @@ bit_expression
|
||||
additive_expression
|
||||
: bit_expression
|
||||
| additive_expression '+' bit_expression
|
||||
| additive_expression ADDW bit_expression
|
||||
| additive_expression ADD_MOD bit_expression
|
||||
| additive_expression '-' bit_expression
|
||||
| additive_expression SUBW bit_expression
|
||||
| additive_expression SUB_MOD bit_expression
|
||||
;
|
||||
|
||||
relational_expression
|
||||
@@ -172,6 +175,9 @@ assignment_operator
|
||||
| AND_ASSIGN
|
||||
| XOR_ASSIGN
|
||||
| OR_ASSIGN
|
||||
| MULT_MOD_ASSIGN
|
||||
| ADD_MOD_ASSIGN
|
||||
| SUB_MOD_ASSIGN
|
||||
;
|
||||
|
||||
constant_expression
|
||||
@@ -201,8 +207,8 @@ identifier_list
|
||||
macro_argument
|
||||
: CT_IDENT
|
||||
| IDENT
|
||||
| type_expression IDENT
|
||||
| type_expression CT_IDENT
|
||||
| type IDENT
|
||||
| type CT_IDENT
|
||||
;
|
||||
|
||||
macro_argument_list
|
||||
@@ -211,20 +217,20 @@ macro_argument_list
|
||||
;
|
||||
|
||||
declaration
|
||||
: type_expression IDENT '=' initializer
|
||||
| type_expression IDENT
|
||||
: type IDENT '=' initializer
|
||||
| type IDENT
|
||||
;
|
||||
|
||||
param_declaration
|
||||
: type_expression
|
||||
| type_expression IDENT
|
||||
| type_expression IDENT '=' initializer
|
||||
: type
|
||||
| type IDENT
|
||||
| type IDENT '=' initializer
|
||||
;
|
||||
|
||||
parameter_type_list
|
||||
: parameter_list
|
||||
| parameter_list ',' ELLIPSIS
|
||||
| parameter_list ',' type_expression ELLIPSIS
|
||||
| parameter_list ',' type ELLIPSIS
|
||||
;
|
||||
|
||||
opt_parameter_type_list
|
||||
@@ -253,15 +259,15 @@ base_type
|
||||
| DOUBLE
|
||||
| TYPE_IDENT
|
||||
| path TYPE_IDENT
|
||||
| TYPE '(' constant_expression ')'
|
||||
| CT_TYPE_IDENT
|
||||
;
|
||||
|
||||
type_expression
|
||||
type
|
||||
: base_type
|
||||
| type_expression '*'
|
||||
| type_expression '[' constant_expression ']'
|
||||
| type_expression '[' ']'
|
||||
| type_expression '[' '+' ']'
|
||||
| type '*'
|
||||
| type '[' constant_expression ']'
|
||||
| type '[' ']'
|
||||
| type '[' '+' ']'
|
||||
;
|
||||
|
||||
initializer
|
||||
@@ -345,7 +351,7 @@ defer_statement
|
||||
;
|
||||
|
||||
catch_statement
|
||||
: CATCH '(' type_expression IDENT ')' defer_catch_body
|
||||
: CATCH '(' type IDENT ')' defer_catch_body
|
||||
| CATCH '(' ERROR IDENT ')' defer_catch_body
|
||||
;
|
||||
|
||||
@@ -437,8 +443,8 @@ path_ident
|
||||
;
|
||||
|
||||
attribute
|
||||
: AT path_ident
|
||||
| AT path_ident '(' constant_expression ')'
|
||||
: '@' path_ident
|
||||
| '@' path_ident '(' constant_expression ')'
|
||||
;
|
||||
|
||||
attribute_list
|
||||
@@ -479,7 +485,7 @@ func_name
|
||||
;
|
||||
|
||||
func_declaration
|
||||
: FUNC type_expression func_name opt_parameter_type_list opt_attributes opt_throw_declaration
|
||||
: FUNC type func_name opt_parameter_type_list opt_attributes opt_throw_declaration
|
||||
;
|
||||
|
||||
func_definition
|
||||
@@ -488,7 +494,7 @@ func_definition
|
||||
;
|
||||
|
||||
macro_declaration
|
||||
: MACRO type_expression IDENT '(' macro_argument_list ')' compound_statement
|
||||
: MACRO type IDENT '(' macro_argument_list ')' compound_statement
|
||||
: MACRO IDENT '(' macro_argument_list ')' compound_statement
|
||||
;
|
||||
|
||||
@@ -512,13 +518,13 @@ struct_declaration_list
|
||||
;
|
||||
|
||||
struct_member_declaration
|
||||
: type_expression identifier_list opt_attributes ';'
|
||||
: type identifier_list opt_attributes ';'
|
||||
| struct_or_union IDENT opt_attributes struct_body
|
||||
| struct_or_union opt_attributes struct_body
|
||||
;
|
||||
|
||||
enum_declaration
|
||||
: ENUM TYPE_IDENT ':' type_expression opt_attributes '{' enumerator_list '}'
|
||||
: ENUM TYPE_IDENT ':' type opt_attributes '{' enumerator_list '}'
|
||||
| ENUM TYPE_IDENT opt_attributes '{' enumerator_list '}'
|
||||
;
|
||||
|
||||
@@ -537,8 +543,8 @@ error_declaration
|
||||
;
|
||||
|
||||
type_list
|
||||
: type_expression
|
||||
| type_list ',' type_expression
|
||||
: type
|
||||
| type_list ',' type
|
||||
;
|
||||
|
||||
generics_case
|
||||
@@ -551,20 +557,20 @@ generics_body
|
||||
|
||||
generics_declaration
|
||||
: GENERIC IDENT '(' macro_argument_list ')' '{' generics_body '}'
|
||||
| GENERIC type_expression IDENT '(' macro_argument_list ')' '{' generics_body '}'
|
||||
| GENERIC type IDENT '(' macro_argument_list ')' '{' generics_body '}'
|
||||
;
|
||||
|
||||
const_declaration
|
||||
: CONST CT_IDENT '=' initializer ';'
|
||||
| CONST type_expression IDENT '=' initializer ';'
|
||||
: CONST CT_CONST_IDENT '=' initializer ';'
|
||||
| CONST type CONST_IDENT '=' initializer ';'
|
||||
;
|
||||
|
||||
func_typedef
|
||||
: FUNC type_expression opt_parameter_type_list opt_throw_declaration
|
||||
: FUNC type opt_parameter_type_list opt_throw_declaration
|
||||
;
|
||||
|
||||
typedef_declaration
|
||||
: TYPEDEF type_expression AS TYPE_IDENT ';'
|
||||
: TYPEDEF type AS TYPE_IDENT ';'
|
||||
| TYPEDEF func_typedef AS TYPE_IDENT ';'
|
||||
;
|
||||
|
||||
@@ -590,8 +596,8 @@ attribute_declaration
|
||||
;
|
||||
|
||||
global_declaration
|
||||
: type_expression IDENT ';'
|
||||
| type_expression IDENT '=' initializer ';'
|
||||
: type IDENT ';'
|
||||
| type IDENT '=' initializer ';'
|
||||
;
|
||||
|
||||
ct_if
|
||||
@@ -640,6 +646,7 @@ module_param
|
||||
: CT_IDENT
|
||||
| HASH_IDENT
|
||||
| TYPE_IDENT
|
||||
| CT_TYPE_IDENT
|
||||
| IDENT
|
||||
;
|
||||
|
||||
@@ -656,12 +663,11 @@ module
|
||||
specified_import
|
||||
: IDENT AS IDENT
|
||||
| IDENT
|
||||
| TYPE
|
||||
| CONST
|
||||
| MACRO
|
||||
| TYPE AS TYPE
|
||||
| CONST AS CONST
|
||||
| MACRO AS MACRO
|
||||
| CONST_IDENT
|
||||
| '@' IDENT
|
||||
| TYPE_IDENT AS TYPE_IDENT
|
||||
| CONST_IDENT AS CONST_IDENT
|
||||
| '@' IDENT AS '@' IDENT
|
||||
;
|
||||
|
||||
specified_import_list
|
||||
|
||||
99
resources/lib/system/builtin.c3
Normal file
99
resources/lib/system/builtin.c3
Normal file
@@ -0,0 +1,99 @@
|
||||
module system::builtin;
|
||||
|
||||
enum TypeKind
|
||||
{
|
||||
VOID,
|
||||
BOOL,
|
||||
FLOAT,
|
||||
INTEGER,
|
||||
STRUCT,
|
||||
UNION,
|
||||
ERROR,
|
||||
ENUM,
|
||||
ARRAY,
|
||||
POINTER,
|
||||
VAR_ARRAY,
|
||||
SUBARRAY,
|
||||
OPAQUE
|
||||
// ALIAS,
|
||||
}
|
||||
|
||||
struct TypeData
|
||||
{
|
||||
typeid typeId;
|
||||
TypeKind kind;
|
||||
int size;
|
||||
int alignment;
|
||||
char* name;
|
||||
char* fullName;
|
||||
}
|
||||
|
||||
struct TypeAlias
|
||||
{
|
||||
TypeData;
|
||||
typeid aliasType;
|
||||
}
|
||||
|
||||
struct TypeError
|
||||
{
|
||||
TypeData;
|
||||
TypeErrorValue[] errors;
|
||||
}
|
||||
|
||||
struct TypeArray
|
||||
{
|
||||
TypeData;
|
||||
typeid elementType;
|
||||
ulong elements;
|
||||
}
|
||||
|
||||
struct TypeVarArray
|
||||
{
|
||||
TypeData;
|
||||
typeid elementType;
|
||||
}
|
||||
|
||||
struct TypeSubarray
|
||||
{
|
||||
TypeData;
|
||||
typeid elementType;
|
||||
}
|
||||
|
||||
struct TypePointer
|
||||
{
|
||||
TypeData;
|
||||
typeid baseType;
|
||||
}
|
||||
|
||||
struct TypeStruct
|
||||
{
|
||||
TypeData;
|
||||
TypeData*[] fields;
|
||||
}
|
||||
|
||||
struct TypeUnion
|
||||
{
|
||||
TypeData;
|
||||
TypeData*[] variants;
|
||||
}
|
||||
|
||||
struct TypeEnum
|
||||
{
|
||||
TypeData;
|
||||
typeid valueType;
|
||||
TypeData*[] associated_value_types;
|
||||
}
|
||||
|
||||
|
||||
struct TypeEnumValue
|
||||
{
|
||||
char* name;
|
||||
ulong value;
|
||||
void*[] associated_values;
|
||||
}
|
||||
|
||||
struct TypeErrorValue
|
||||
{
|
||||
char* name;
|
||||
ulong value;
|
||||
}
|
||||
@@ -607,24 +607,25 @@ struct WithArray
|
||||
{
|
||||
int[4] x;
|
||||
}
|
||||
/*
|
||||
|
||||
error Err
|
||||
{
|
||||
TEST_ERR1
|
||||
}
|
||||
*/
|
||||
/*
|
||||
|
||||
|
||||
func int testThrow(int x) throws Err
|
||||
{
|
||||
if (x < 0) throw Err.TEST_ERR1;
|
||||
return x * x;
|
||||
}
|
||||
*/
|
||||
|
||||
func void testErrors()
|
||||
{
|
||||
//int x = try testThrow(20) else 0;
|
||||
int x = 0;
|
||||
int x = try testThrow(20) else 1;
|
||||
printf("Value was %d, expected 400.\n", x);
|
||||
x = try testThrow(-1) else 20;
|
||||
printf("Value was %d, expected 20.\n", x);
|
||||
}
|
||||
|
||||
func void testArray()
|
||||
@@ -683,9 +684,18 @@ JUMP:
|
||||
printf("6");
|
||||
}
|
||||
|
||||
func void testType()
|
||||
{
|
||||
printf("Test type\n");
|
||||
typeid x = WithArray.typeid;
|
||||
int y = 0;
|
||||
Teob b;
|
||||
typeid structSize = typeof(b);
|
||||
}
|
||||
|
||||
func int main(int x)
|
||||
{
|
||||
|
||||
printf("Helo!\n");
|
||||
testErrors();
|
||||
testDefault(y = 99);
|
||||
@@ -695,6 +705,7 @@ func int main(int x)
|
||||
testAnonStruct();
|
||||
testSimpleStruct(0);
|
||||
testUnion();
|
||||
testType();
|
||||
int efd = 9;
|
||||
uint fefoek = 1;
|
||||
printf("Helo: %d\n", efd + cast(fefoek, int));
|
||||
|
||||
@@ -553,10 +553,10 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
|
||||
fprint_expr_common(file, expr, indent + 1);
|
||||
fprint_expr_recursive(file, expr->access_expr.parent, indent + 1);
|
||||
break;
|
||||
case EXPR_TYPE:
|
||||
fprintf_indented(file, indent, "(type\n");
|
||||
case EXPR_TYPEID:
|
||||
fprintf_indented(file, indent, "(typeid \n");
|
||||
fprint_expr_common(file, expr, indent + 1);
|
||||
fprint_type_info_recursive(file, expr->type_expr.type, indent + 1);
|
||||
fprint_type_info_recursive(file, expr->typeid_expr, indent + 1);
|
||||
break;
|
||||
case EXPR_GROUP:
|
||||
fprintf_indented(file, indent, "(group\n");
|
||||
|
||||
@@ -183,6 +183,7 @@ struct _Type
|
||||
const char *name;
|
||||
Type **type_cache;
|
||||
void *backend_type;
|
||||
void *backend_typeid;
|
||||
void *backend_debug_type;
|
||||
union
|
||||
{
|
||||
@@ -438,7 +439,7 @@ typedef struct
|
||||
Token name;
|
||||
Decl *method;
|
||||
};
|
||||
} ExprTypeRef;
|
||||
} ExprTypeAccess;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -505,11 +506,6 @@ typedef struct
|
||||
Decl *decl;
|
||||
} ExprIdentifier;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TypeInfo *type;
|
||||
} ExprType;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -575,10 +571,11 @@ struct _Expr
|
||||
ExprDesignatedInit designated_init_expr;
|
||||
Expr *group_expr;
|
||||
ExprCast cast_expr;
|
||||
Expr *typeof_expr;
|
||||
ExprConst const_expr;
|
||||
ExprRange range_expr;
|
||||
ExprStructValue struct_value_expr;
|
||||
ExprTypeRef type_access;
|
||||
ExprTypeAccess type_access;
|
||||
ExprTry try_expr;
|
||||
Expr* macro_expr;
|
||||
ExprBinary binary_expr;
|
||||
@@ -589,7 +586,7 @@ struct _Expr
|
||||
ExprSubscript subscript_expr;
|
||||
ExprAccess access_expr;
|
||||
ExprIdentifier identifier_expr;
|
||||
ExprType type_expr;
|
||||
TypeInfo *typeid_expr;
|
||||
ExprInitializer expr_initializer;
|
||||
ExprCompoundLiteral expr_compound_literal;
|
||||
Expr** expression_list;
|
||||
|
||||
@@ -216,17 +216,17 @@ typedef enum
|
||||
EXPR_TERNARY,
|
||||
EXPR_UNARY,
|
||||
EXPR_POST_UNARY,
|
||||
EXPR_TYPE,
|
||||
EXPR_TYPEID,
|
||||
EXPR_IDENTIFIER,
|
||||
EXPR_TYPE_ACCESS,
|
||||
EXPR_CALL,
|
||||
EXPR_GROUP,
|
||||
EXPR_SIZEOF,
|
||||
EXPR_SUBSCRIPT,
|
||||
EXPR_ACCESS,
|
||||
EXPR_INITIALIZER_LIST,
|
||||
EXPR_EXPRESSION_LIST,
|
||||
EXPR_CAST,
|
||||
EXPR_TYPEOF,
|
||||
EXPR_SCOPED_EXPR,
|
||||
EXPR_MACRO_EXPR,
|
||||
EXPR_EXPR_BLOCK,
|
||||
@@ -375,6 +375,7 @@ typedef enum
|
||||
TOKEN_USHORT,
|
||||
TOKEN_USIZE,
|
||||
TOKEN_QUAD,
|
||||
TOKEN_TYPEID,
|
||||
|
||||
// C types
|
||||
TOKEN_C_SHORT,
|
||||
@@ -393,10 +394,11 @@ typedef enum
|
||||
TOKEN_CONST_IDENT, // Any purely upper case ident,
|
||||
TOKEN_TYPE_IDENT, // Any ident on the format FooBar or __FooBar
|
||||
|
||||
// We want to parse #foo / $foo separately.
|
||||
// We want to parse $foo separately.
|
||||
// Otherwise we allow things like "# foo" which would be pretty bad.
|
||||
TOKEN_HASH_IDENT, // #foobar
|
||||
TOKEN_CT_IDENT, // $foobar
|
||||
TOKEN_CT_CONST_IDENT, // $FOOBAR
|
||||
TOKEN_CT_TYPE_IDENT, // $Foobar
|
||||
|
||||
TOKEN_STRING, // "Teststring"
|
||||
TOKEN_INTEGER, // 123 0x23 0b10010 0o327
|
||||
@@ -444,13 +446,13 @@ typedef enum
|
||||
TOKEN_THROWS,
|
||||
TOKEN_TRUE,
|
||||
TOKEN_TRY,
|
||||
TOKEN_TYPE, // Reserved
|
||||
TOKEN_TYPEDEF,
|
||||
TOKEN_UNION,
|
||||
TOKEN_UNTIL,
|
||||
TOKEN_VAR, // Reserved
|
||||
TOKEN_VOLATILE,
|
||||
TOKEN_WHILE,
|
||||
TOKEN_TYPEOF,
|
||||
|
||||
TOKEN_CT_CASE, // $case
|
||||
TOKEN_CT_DEFAULT, // $default
|
||||
|
||||
@@ -240,11 +240,14 @@ static inline Token scan_prefixed_ident(Lexer *lexer, TokenType type, TokenType
|
||||
|
||||
// Parses identifiers. Note that this is a bit complicated here since
|
||||
// we split identifiers into 2 types + find keywords.
|
||||
static inline Token scan_ident(Lexer *lexer)
|
||||
static inline Token scan_ident(Lexer *lexer, TokenType normal, TokenType const_token, TokenType type_token, char prefix)
|
||||
{
|
||||
|
||||
TokenType type = 0;
|
||||
uint32_t hash = FNV1_SEED;
|
||||
if (prefix)
|
||||
{
|
||||
hash = FNV1a(prefix, hash);
|
||||
}
|
||||
while (peek(lexer) == '_')
|
||||
{
|
||||
hash = FNV1a(next(lexer), hash);
|
||||
@@ -261,11 +264,11 @@ static inline Token scan_ident(Lexer *lexer)
|
||||
case 'z':
|
||||
if (!type)
|
||||
{
|
||||
type = TOKEN_IDENT;
|
||||
type = normal;
|
||||
}
|
||||
else if (type == TOKEN_CONST_IDENT)
|
||||
else if (type == const_token)
|
||||
{
|
||||
type = TOKEN_TYPE_IDENT;
|
||||
type = type_token;
|
||||
}
|
||||
break;
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||
@@ -274,7 +277,7 @@ static inline Token scan_ident(Lexer *lexer)
|
||||
case 'P': case 'Q': case 'R': case 'S': case 'T':
|
||||
case 'U': case 'V': case 'W': case 'X': case 'Y':
|
||||
case 'Z':
|
||||
if (!type) type = TOKEN_CONST_IDENT;
|
||||
if (!type) type = const_token;
|
||||
break;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
@@ -286,6 +289,11 @@ static inline Token scan_ident(Lexer *lexer)
|
||||
}
|
||||
hash = FNV1a(next(lexer), hash);
|
||||
}
|
||||
// Allow bang!
|
||||
if (peek(lexer) == '!' && type == normal)
|
||||
{
|
||||
hash = FNV1a(next(lexer), hash);
|
||||
}
|
||||
EXIT:;
|
||||
uint32_t len = lexer->current - lexer->lexing_start;
|
||||
const char* interned_string = symtab_add(lexer->lexing_start, len, hash, &type);
|
||||
@@ -485,9 +493,9 @@ Token lexer_scan_token(Lexer *lexer)
|
||||
case '"':
|
||||
return scan_string(lexer);
|
||||
case '#':
|
||||
return scan_prefixed_ident(lexer, TOKEN_HASH_IDENT, TOKEN_HASH, false, "#");
|
||||
return make_token(lexer, TOKEN_HASH, "#");
|
||||
case '$':
|
||||
return scan_prefixed_ident(lexer, TOKEN_CT_IDENT, TOKEN_DOLLAR, false, "$");
|
||||
return scan_ident(lexer, TOKEN_CT_TYPE_IDENT, TOKEN_CT_CONST_IDENT, TOKEN_CT_TYPE_IDENT, '$');
|
||||
case ',':
|
||||
return make_token(lexer, TOKEN_COMMA, ",");
|
||||
case ';':
|
||||
@@ -556,7 +564,7 @@ Token lexer_scan_token(Lexer *lexer)
|
||||
if (is_alphanum_(c))
|
||||
{
|
||||
backtrack(lexer);
|
||||
return is_digit(c) ? scan_digit(lexer) : scan_ident(lexer);
|
||||
return is_digit(c) ? scan_digit(lexer) : scan_ident(lexer, TOKEN_IDENT, TOKEN_CONST_IDENT, TOKEN_TYPE_IDENT, 0);
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
@@ -610,12 +618,7 @@ Token lexer_scan_ident_test(Lexer *lexer, const char *scan)
|
||||
if (scan[0] == '$')
|
||||
{
|
||||
next(lexer);
|
||||
return scan_prefixed_ident(lexer, TOKEN_CT_IDENT, TOKEN_DOLLAR, false, "$");
|
||||
return scan_ident(lexer, TOKEN_CT_IDENT, TOKEN_CT_CONST_IDENT, TOKEN_CT_TYPE_IDENT, '$');
|
||||
}
|
||||
if (scan[0] == '#')
|
||||
{
|
||||
next(lexer);
|
||||
return scan_prefixed_ident(lexer, TOKEN_HASH_IDENT, TOKEN_HASH, false, "#");
|
||||
}
|
||||
return scan_ident(lexer);
|
||||
return scan_ident(lexer, TOKEN_IDENT, TOKEN_CONST_IDENT, TOKEN_TYPE_IDENT, 0);
|
||||
}
|
||||
|
||||
@@ -254,6 +254,73 @@ void llvm_codegen_setup()
|
||||
intrinsics_setup = true;
|
||||
}
|
||||
|
||||
void gencontext_emit_struct_decl(GenContext *context, Decl *decl)
|
||||
{
|
||||
llvm_type(decl->type);
|
||||
LLVMValueRef global_name = LLVMAddGlobal(context->module, llvm_type(type_bool), decl->name);
|
||||
LLVMSetLinkage(global_name, LLVMInternalLinkage);
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetInitializer(global_name, LLVMConstInt(llvm_type(type_bool), 1, false));
|
||||
|
||||
decl->type->backend_typeid = global_name;
|
||||
switch (decl->visibility)
|
||||
{
|
||||
case VISIBLE_MODULE:
|
||||
LLVMSetVisibility(decl->var.backend_ref, LLVMProtectedVisibility);
|
||||
break;
|
||||
case VISIBLE_PUBLIC:
|
||||
LLVMSetVisibility(decl->var.backend_ref, LLVMDefaultVisibility);
|
||||
break;
|
||||
case VISIBLE_EXTERN:
|
||||
case VISIBLE_LOCAL:
|
||||
LLVMSetVisibility(decl->var.backend_ref, LLVMHiddenVisibility);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void gencontext_emit_decl(GenContext *context, Decl *decl)
|
||||
{
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_POISONED:
|
||||
UNREACHABLE;
|
||||
case DECL_FUNC:
|
||||
// TODO
|
||||
break;
|
||||
case DECL_VAR:
|
||||
// TODO
|
||||
break;
|
||||
case DECL_TYPEDEF:
|
||||
break;
|
||||
case DECL_ENUM_CONSTANT:
|
||||
// TODO
|
||||
break;;
|
||||
case DECL_STRUCT:
|
||||
case DECL_UNION:
|
||||
gencontext_emit_struct_decl(context, decl);
|
||||
break;
|
||||
case DECL_ENUM:
|
||||
// TODO
|
||||
break;
|
||||
case DECL_ERROR:
|
||||
// TODO
|
||||
break;;
|
||||
case DECL_ERROR_CONSTANT:
|
||||
//TODO
|
||||
break;;
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_IMPORT:
|
||||
case DECL_MACRO:
|
||||
case DECL_GENERIC:
|
||||
case DECL_CT_IF:
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_THROWS:
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
|
||||
void llvm_codegen(Context *context)
|
||||
{
|
||||
assert(intrinsics_setup);
|
||||
@@ -269,6 +336,10 @@ void llvm_codegen(Context *context)
|
||||
{
|
||||
gencontext_emit_function_decl(&gen_context, context->functions[i]);
|
||||
}
|
||||
VECEACH(context->types, i)
|
||||
{
|
||||
gencontext_emit_decl(&gen_context, context->types[i]);
|
||||
}
|
||||
VECEACH(context->functions, i)
|
||||
{
|
||||
Decl *decl = context->functions[i];
|
||||
|
||||
@@ -6,6 +6,15 @@
|
||||
#include "compiler_internal.h"
|
||||
#include "bigint.h"
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_const_int(GenContext *context, Type *type, uint64_t val)
|
||||
{
|
||||
type = type->canonical;
|
||||
assert(type_is_any_integer(type) || type->type_kind == TYPE_BOOL);
|
||||
return LLVMConstInt(llvm_type(type), val, type_is_signed_integer(type));
|
||||
}
|
||||
|
||||
#define llvm_int(_type, _val) gencontext_emit_const_int(context, _type, _val)
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_add_int(GenContext *context, Type *type, bool use_mod, LLVMValueRef left, LLVMValueRef right)
|
||||
{
|
||||
if (use_mod)
|
||||
@@ -88,7 +97,7 @@ static inline LLVMValueRef gencontext_emit_subscript_addr(GenContext *context, E
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
// TODO insert trap on overflow.
|
||||
LLVMValueRef zero = LLVMConstInt(llvm_type(type_int), 0, false);
|
||||
LLVMValueRef zero = llvm_int(type_int, 0);
|
||||
LLVMValueRef indices[2] = {
|
||||
zero,
|
||||
index_value,
|
||||
@@ -172,6 +181,7 @@ LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
|
||||
case EXPR_DESIGNATED_INITIALIZER:
|
||||
// Should only appear when generating designated initializers.
|
||||
UNREACHABLE
|
||||
|
||||
case EXPR_IDENTIFIER:
|
||||
return expr->identifier_expr.decl->var.backend_ref;
|
||||
case EXPR_UNARY:
|
||||
@@ -188,10 +198,9 @@ LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
|
||||
case EXPR_GROUP:
|
||||
return gencontext_emit_address(context, expr->group_expr);
|
||||
case EXPR_CONST:
|
||||
case EXPR_TYPE:
|
||||
case EXPR_TYPEID:
|
||||
case EXPR_POISONED:
|
||||
case EXPR_TRY:
|
||||
case EXPR_SIZEOF:
|
||||
case EXPR_BINARY:
|
||||
case EXPR_TERNARY:
|
||||
case EXPR_POST_UNARY:
|
||||
@@ -201,6 +210,7 @@ LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
case EXPR_CAST:
|
||||
case EXPR_MACRO_EXPR:
|
||||
case EXPR_TYPEOF:
|
||||
UNREACHABLE
|
||||
}
|
||||
UNREACHABLE
|
||||
@@ -345,7 +355,7 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr_addr(GenContext
|
||||
case DESIGNATED_SUBSCRIPT:
|
||||
{
|
||||
// TODO range, more arrays
|
||||
LLVMValueRef zero = LLVMConstInt(llvm_type(type_int), 0, false);
|
||||
LLVMValueRef zero = llvm_int(type_int, 0);
|
||||
LLVMValueRef index = gencontext_emit_expr(context, path->index_expr);
|
||||
LLVMValueRef indices[2] = {
|
||||
zero,
|
||||
@@ -418,7 +428,8 @@ LLVMValueRef gencontext_emit_unary_expr(GenContext *context, Expr *expr)
|
||||
case UNARYOP_ERROR:
|
||||
FATAL_ERROR("Illegal unary op %s", expr->unary_expr.operator);
|
||||
case UNARYOP_NOT:
|
||||
return LLVMBuildXor(context->builder, gencontext_emit_expr(context, expr->unary_expr.expr), LLVMConstInt(llvm_type(type_bool), 1, 0), "not");
|
||||
return LLVMBuildXor(context->builder, gencontext_emit_expr(context, expr->unary_expr.expr),
|
||||
llvm_int(type_bool, 1), "not");
|
||||
case UNARYOP_BITNEG:
|
||||
return LLVMBuildNot(context->builder, gencontext_emit_expr(context, expr->unary_expr.expr), "bnot");
|
||||
case UNARYOP_NEGMOD:
|
||||
@@ -431,7 +442,7 @@ LLVMValueRef gencontext_emit_unary_expr(GenContext *context, Expr *expr)
|
||||
assert(!type_is_unsigned(type));
|
||||
{
|
||||
LLVMValueRef to_negate = gencontext_emit_expr(context, expr->unary_expr.expr);
|
||||
LLVMValueRef zero = LLVMConstInt(llvm_type(expr->unary_expr.expr->type->canonical), 0, false);
|
||||
LLVMValueRef zero = llvm_int(expr->unary_expr.expr->type, 0);
|
||||
if (build_options.debug_mode)
|
||||
{
|
||||
LLVMTypeRef type_to_use = llvm_type(type->canonical);
|
||||
@@ -491,7 +502,7 @@ static LLVMValueRef gencontext_emit_logical_and_or(GenContext *context, Expr *ex
|
||||
LLVMValueRef phi = LLVMBuildPhi(context->builder, llvm_type(type_bool), "val");
|
||||
|
||||
// Simplify for LLVM by entering the constants we already know of.
|
||||
LLVMValueRef result_on_skip = LLVMConstInt(LLVMInt1TypeInContext(context->context), op == BINARYOP_AND ? 0 : 1, false);
|
||||
LLVMValueRef result_on_skip = llvm_int(type_bool, op == BINARYOP_AND ? 0 : 1);
|
||||
LLVMValueRef logic_values[2] = { result_on_skip, rhs };
|
||||
LLVMBasicBlockRef blocks[2] = { start_block, rhs_block };
|
||||
LLVMAddIncoming(phi, logic_values, blocks, 2);
|
||||
@@ -591,7 +602,7 @@ static LLVMValueRef gencontext_emit_int_comparison(GenContext *context, Type *lh
|
||||
if (rhs_signed) return comp_value;
|
||||
|
||||
// Otherwise, special handling for left side signed, right side unsigned.
|
||||
LLVMValueRef zero = LLVMConstInt(llvm_type(lhs_type), 0, true);
|
||||
LLVMValueRef zero = llvm_int(lhs_type, 0);
|
||||
switch (binary_op)
|
||||
{
|
||||
case BINARYOP_EQ:
|
||||
@@ -773,6 +784,12 @@ LLVMValueRef gencontext_emit_post_unary_expr(GenContext *context, Expr *expr)
|
||||
return gencontext_emit_post_inc_dec(context, expr->post_expr.expr, expr->post_expr.operator == POSTUNARYOP_INC ? 1 : -1, false);
|
||||
}
|
||||
|
||||
LLVMValueRef gencontext_emit_typeid(GenContext *context, Expr *expr)
|
||||
{
|
||||
assert(expr->typeid_expr->type->backend_typeid);
|
||||
return expr->typeid_expr->type->backend_typeid;
|
||||
}
|
||||
|
||||
LLVMValueRef gencontext_emit_try_expr(GenContext *context, Expr *expr)
|
||||
{
|
||||
if (expr->try_expr.else_expr)
|
||||
@@ -884,27 +901,27 @@ LLVMValueRef gencontext_emit_ternary_expr(GenContext *context, Expr *expr)
|
||||
|
||||
LLVMValueRef gencontext_emit_const_expr(GenContext *context, Expr *expr)
|
||||
{
|
||||
LLVMTypeRef type = llvm_type(type_reduced_from_expr(expr));
|
||||
Type *type = type_reduced_from_expr(expr)->canonical;
|
||||
switch (expr->const_expr.kind)
|
||||
{
|
||||
case ALL_INTS:
|
||||
if (type_is_unsigned(expr->type->canonical))
|
||||
if (type_is_unsigned(type))
|
||||
{
|
||||
return LLVMConstInt(type, bigint_as_unsigned(&expr->const_expr.i), false);
|
||||
return llvm_int(type, bigint_as_unsigned(&expr->const_expr.i));
|
||||
}
|
||||
else
|
||||
{
|
||||
return LLVMConstInt(type, (uint64_t)bigint_as_signed(&expr->const_expr.i), false);
|
||||
return llvm_int(type, bigint_as_signed(&expr->const_expr.i));
|
||||
}
|
||||
case ALL_FLOATS:
|
||||
return LLVMConstReal(type, (double) expr->const_expr.f);
|
||||
return LLVMConstReal(llvm_type(type), (double) expr->const_expr.f);
|
||||
case TYPE_POINTER:
|
||||
return LLVMConstNull(type);
|
||||
return LLVMConstNull(llvm_type(type));
|
||||
case TYPE_BOOL:
|
||||
return LLVMConstInt(type, expr->const_expr.b ? 1 : 0, false);
|
||||
return llvm_int(type, expr->const_expr.b ? 1 : 0);
|
||||
case TYPE_STRING:
|
||||
{
|
||||
LLVMValueRef global_name = LLVMAddGlobal(context->module, type, "string");
|
||||
LLVMValueRef global_name = LLVMAddGlobal(context->module, llvm_type(type), "string");
|
||||
LLVMSetLinkage(global_name, LLVMInternalLinkage);
|
||||
LLVMSetGlobalConstant(global_name, 1);
|
||||
LLVMSetInitializer(global_name, LLVMConstStringInContext(context->context,
|
||||
@@ -918,9 +935,9 @@ LLVMValueRef gencontext_emit_const_expr(GenContext *context, Expr *expr)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gencontext_emit_throw_branch(GenContext *context, LLVMValueRef value)
|
||||
static inline void gencontext_emit_throw_branch(GenContext *context, LLVMValueRef value, Type *error_type)
|
||||
{
|
||||
LLVMBasicBlockRef after_block = gencontext_create_free_block(context, "");
|
||||
LLVMBasicBlockRef after_block = gencontext_create_free_block(context, "throwafter");
|
||||
size_t catch_index = context->catch_stack_index;
|
||||
while (catch_index > 0)
|
||||
{
|
||||
@@ -929,7 +946,9 @@ static inline void gencontext_emit_throw_branch(GenContext *context, LLVMValueRe
|
||||
Catch *current_catch = &context->catch_stack[catch_index];
|
||||
if (!current_catch->decl)
|
||||
{
|
||||
gencontext_emit_cond_br(context, value, current_catch->catch_block, after_block);
|
||||
|
||||
LLVMValueRef comparison = LLVMBuildICmp(context->builder, LLVMIntNE, llvm_int(error_type, 0), value, "checkerr");
|
||||
gencontext_emit_cond_br(context, comparison, current_catch->catch_block, after_block);
|
||||
gencontext_emit_block(context, after_block);
|
||||
return;
|
||||
}
|
||||
@@ -979,11 +998,11 @@ LLVMValueRef gencontext_emit_call_expr(GenContext *context, Expr *expr)
|
||||
{
|
||||
LLVMValueRef maybe_error = gencontext_emit_load(context, type_error_union, error_param);
|
||||
TODO // Incorrect, must get subset if this is 128 bits
|
||||
gencontext_emit_throw_branch(context, maybe_error);
|
||||
gencontext_emit_throw_branch(context, maybe_error, type_error_union);
|
||||
}
|
||||
else
|
||||
{
|
||||
gencontext_emit_throw_branch(context, call);
|
||||
gencontext_emit_throw_branch(context, call, type_reduced(type_error));
|
||||
}
|
||||
}
|
||||
// If we used a return param, then load that info here.
|
||||
@@ -1102,10 +1121,11 @@ NESTED_RETRY:
|
||||
return gencontext_emit_post_unary_expr(context, expr);
|
||||
case EXPR_TRY:
|
||||
return gencontext_emit_try_expr(context, expr);
|
||||
case EXPR_TYPE:
|
||||
case EXPR_SIZEOF:
|
||||
case EXPR_TYPEID:
|
||||
return gencontext_emit_typeid(context, expr);
|
||||
case EXPR_TYPE_ACCESS:
|
||||
case EXPR_MACRO_EXPR:
|
||||
case EXPR_TYPEOF:
|
||||
// These are folded in the semantic analysis step.
|
||||
UNREACHABLE
|
||||
case EXPR_IDENTIFIER:
|
||||
|
||||
@@ -231,6 +231,8 @@ void gencontext_emit_function_decl(GenContext *context, Decl *decl)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void gencontext_emit_extern_decl(GenContext *context, Decl *decl)
|
||||
{
|
||||
switch (decl->decl_kind)
|
||||
@@ -253,6 +255,7 @@ void gencontext_emit_extern_decl(GenContext *context, Decl *decl)
|
||||
case DECL_STRUCT:
|
||||
case DECL_UNION:
|
||||
llvm_type(decl->type);
|
||||
TODO // Fix typeid
|
||||
break;
|
||||
case DECL_ENUM:
|
||||
TODO
|
||||
|
||||
@@ -76,6 +76,7 @@ typedef struct
|
||||
LLVMBasicBlockRef expr_block_exit;
|
||||
bool current_block_is_target : 1;
|
||||
bool did_call_stack_save : 1;
|
||||
LLVMTypeRef type_data_definitions[TYPE_KINDS];
|
||||
} GenContext;
|
||||
|
||||
extern unsigned sadd_overflow_intrinsic_id;
|
||||
|
||||
@@ -10,6 +10,8 @@ static inline LLVMTypeRef gencontext_create_basic_llvm_type(GenContext *context,
|
||||
{
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_META_TYPE:
|
||||
return LLVMIntTypeInContext(context->context, type->builtin.bitsize);
|
||||
case TYPE_BOOL:
|
||||
return LLVMInt1TypeInContext(context->context);
|
||||
case TYPE_I8:
|
||||
|
||||
@@ -167,9 +167,10 @@ LLVMTypeRef llvm_get_type(LLVMContextRef context, Type *type)
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_POISONED:
|
||||
case TYPE_META_TYPE:
|
||||
case TYPE_ERROR:
|
||||
UNREACHABLE;
|
||||
case TYPE_META_TYPE:
|
||||
return type->backend_type = LLVMIntTypeInContext(context, type->builtin.bitsize);
|
||||
case TYPE_TYPEDEF:
|
||||
return type->backend_type = llvm_get_type(context, type->canonical);
|
||||
case TYPE_ENUM:
|
||||
|
||||
@@ -96,9 +96,8 @@ bool parse_param_list(Context *context, Expr ***result, bool allow_type)
|
||||
sema_error_range(start, "Did not expect a type here, only expressions.");
|
||||
return false;
|
||||
}
|
||||
expr = expr_new(EXPR_TYPE, start);
|
||||
expr = expr_new(EXPR_TYPEID, type->span);
|
||||
RANGE_EXTEND_PREV(expr);
|
||||
expr->type_expr.type = type;
|
||||
}
|
||||
vec_add(*result, expr);
|
||||
if (!try_consume(context, TOKEN_COMMA))
|
||||
@@ -144,7 +143,7 @@ Expr *parse_expression_list(Context *context)
|
||||
static Expr *parse_type_identifier(Context *context, Expr *left)
|
||||
{
|
||||
assert(!left && "Unexpected left hand side");
|
||||
return parse_type_identifier_with_path(context, NULL);
|
||||
return parse_type_expression_with_path(context, NULL);
|
||||
}
|
||||
static Expr *parse_cast_expr(Context *context, Expr *left)
|
||||
{
|
||||
@@ -154,7 +153,17 @@ static Expr *parse_cast_expr(Context *context, Expr *left)
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_expr);
|
||||
expr->cast_expr.expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
CONSUME_OR(TOKEN_COMMA, poisoned_expr);
|
||||
expr->cast_expr.type_info = TRY_TYPE_OR(parse_type_expression(context), poisoned_expr);
|
||||
expr->cast_expr.type_info = TRY_TYPE_OR(parse_type(context), poisoned_expr);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
|
||||
return expr;
|
||||
}
|
||||
static Expr *parse_typeof_expr(Context *context, Expr *left)
|
||||
{
|
||||
assert(!left && "Unexpected left hand side");
|
||||
Expr *expr = EXPR_NEW_TOKEN(EXPR_TYPEOF, context->tok);
|
||||
advance_and_verify(context, TOKEN_TYPEOF);
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_expr);
|
||||
expr->typeof_expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
|
||||
return expr;
|
||||
}
|
||||
@@ -365,17 +374,6 @@ static Expr *parse_identifier(Context *context, Expr *left)
|
||||
return parse_identifier_with_path(context, NULL);
|
||||
}
|
||||
|
||||
static Expr *parse_type_expr(Context *context, Expr *left)
|
||||
{
|
||||
assert(!left && "Unexpected left hand side");
|
||||
Expr *expr = EXPR_NEW_TOKEN(EXPR_TYPE, context->tok);
|
||||
advance_and_verify(context, TOKEN_TYPE);
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_expr);
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type_expression(context), poisoned_expr);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
|
||||
expr->type_expr.type = type;
|
||||
return expr;
|
||||
}
|
||||
|
||||
static Expr *parse_maybe_scope(Context *context, Expr *left)
|
||||
{
|
||||
@@ -388,7 +386,7 @@ static Expr *parse_maybe_scope(Context *context, Expr *left)
|
||||
case TOKEN_CONST_IDENT:
|
||||
return parse_identifier_with_path(context, path);
|
||||
case TOKEN_TYPE_IDENT:
|
||||
return parse_type_identifier_with_path(context, path);
|
||||
return parse_type_expression_with_path(context, path);
|
||||
default:
|
||||
SEMA_TOKEN_ERROR(context->tok, "Expected a type, function or constant.");
|
||||
return poisoned_expr;
|
||||
@@ -721,6 +719,63 @@ static Expr *parse_nil(Context *context, Expr *left)
|
||||
return number;
|
||||
}
|
||||
|
||||
Expr *parse_type_compound_literal_expr_after_type(Context *context, TypeInfo *type_info)
|
||||
{
|
||||
Expr *expr = expr_new(EXPR_COMPOUND_LITERAL, type_info->span);
|
||||
expr->expr_compound_literal.type_info = type_info;
|
||||
expr->expr_compound_literal.initializer = TRY_EXPR_OR(parse_initializer_list(context), poisoned_expr);
|
||||
RANGE_EXTEND_PREV(expr);
|
||||
return expr;
|
||||
}
|
||||
|
||||
Expr *parse_type_access_expr_after_type(Context *context, TypeInfo *type_info)
|
||||
{
|
||||
switch (context->tok.type)
|
||||
{
|
||||
case TOKEN_TYPEID:
|
||||
case TOKEN_IDENT:
|
||||
case TOKEN_CONST_IDENT:
|
||||
break;
|
||||
default:
|
||||
SEMA_TOKEN_ERROR(context->tok, "Expected the name of a type property here.");
|
||||
return poisoned_expr;
|
||||
}
|
||||
Expr *expr = expr_new(EXPR_TYPE_ACCESS, type_info->span);
|
||||
expr->type_access.type = type_info;
|
||||
expr->type_access.name = context->tok;
|
||||
advance(context);
|
||||
RANGE_EXTEND_PREV(expr);
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* type_identifier
|
||||
* : TYPE_IDENT initializer_list
|
||||
* | TYPE_IDENT method_ref
|
||||
* ;
|
||||
*
|
||||
* @param left must be null.
|
||||
* @return Expr*
|
||||
*/
|
||||
Expr *parse_type_expression_with_path(Context *context, Path *path)
|
||||
{
|
||||
TypeInfo *type = type_info_new(TYPE_INFO_IDENTIFIER, path ? path->span : context->tok.span );
|
||||
type->unresolved.path = path;
|
||||
type->unresolved.name_loc = context->tok;
|
||||
advance_and_verify(context, TOKEN_TYPE_IDENT);
|
||||
RANGE_EXTEND_PREV(type);
|
||||
if (context->tok.type == TOKEN_LBRACE)
|
||||
{
|
||||
return parse_type_compound_literal_expr_after_type(context, type);
|
||||
}
|
||||
CONSUME_OR(TOKEN_DOT, poisoned_expr);
|
||||
return parse_type_access_expr_after_type(context, type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* function_block
|
||||
* : '({' stmt_list '})'
|
||||
@@ -746,10 +801,9 @@ ParseRule rules[TOKEN_EOF + 1] = {
|
||||
[TOKEN_MINUSMINUS] = { parse_unary_expr, parse_post_unary, PREC_CALL },
|
||||
[TOKEN_LPAREN] = { parse_grouping_expr, parse_call_expr, PREC_CALL },
|
||||
[TOKEN_LPARBRA] = { parse_expr_block, NULL, PREC_NONE },
|
||||
[TOKEN_TYPE] = { parse_type_expr, NULL, PREC_NONE },
|
||||
[TOKEN_CAST] = { parse_cast_expr, NULL, PREC_NONE },
|
||||
[TOKEN_TYPEOF] = { parse_typeof_expr, NULL, PREC_NONE },
|
||||
[TOKEN_TRY] = { parse_try_expr, NULL, PREC_TRY },
|
||||
//[TOKEN_SIZEOF] = { parse_sizeof, NULL, PREC_NONE },
|
||||
[TOKEN_LBRACKET] = { NULL, parse_subscript_expr, PREC_CALL },
|
||||
[TOKEN_MINUS] = { parse_unary_expr, parse_binary, PREC_ADDITIVE },
|
||||
[TOKEN_MINUS_MOD] = { parse_unary_expr, parse_binary, PREC_ADDITIVE },
|
||||
|
||||
@@ -91,7 +91,7 @@ static inline Ast* parse_catch_stmt(Context *context)
|
||||
TypeInfo *type = NULL;
|
||||
if (!try_consume(context, TOKEN_ERROR_TYPE))
|
||||
{
|
||||
type = TRY_TYPE_OR(parse_type_expression(context), poisoned_ast);
|
||||
type = TRY_TYPE_OR(parse_type(context), poisoned_ast);
|
||||
}
|
||||
EXPECT_IDENT_FOR_OR("error parameter", poisoned_ast);
|
||||
Decl *decl = decl_new_var(context->tok, type, VARDECL_PARAM, VISIBLE_LOCAL);
|
||||
@@ -569,7 +569,7 @@ static inline Ast* parse_ct_switch_stmt(Context *context)
|
||||
advance(context);
|
||||
while (1)
|
||||
{
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type_expression(context), poisoned_ast);
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), poisoned_ast);
|
||||
vec_add(stmt->ct_case_stmt.types, type);
|
||||
if (!try_consume(context, TOKEN_COMMA)) break;
|
||||
}
|
||||
@@ -632,17 +632,19 @@ Ast *parse_stmt(Context *context)
|
||||
case TOKEN_C_UINT:
|
||||
case TOKEN_C_ULONG:
|
||||
case TOKEN_C_ULONGLONG:
|
||||
case TOKEN_TYPEID:
|
||||
case TOKEN_CT_TYPE_IDENT:
|
||||
case TOKEN_TYPE_IDENT:
|
||||
if (context->next_tok.type == TOKEN_DOT || context->next_tok.type == TOKEN_LBRACE)
|
||||
{
|
||||
return parse_expr_stmt(context);
|
||||
}
|
||||
return parse_declaration_stmt(context);
|
||||
case TOKEN_TYPEOF:
|
||||
TODO
|
||||
case TOKEN_LOCAL: // Local means declaration!
|
||||
case TOKEN_CONST: // Const means declaration!
|
||||
return parse_declaration_stmt(context);
|
||||
case TOKEN_TYPE:
|
||||
return parse_decl_or_expr_stmt(context);
|
||||
case TOKEN_CONST_IDENT:
|
||||
if (context->next_tok.type == TOKEN_COLON)
|
||||
{
|
||||
@@ -725,7 +727,7 @@ Ast *parse_stmt(Context *context)
|
||||
case TOKEN_PLUS:
|
||||
case TOKEN_MINUSMINUS:
|
||||
case TOKEN_PLUSPLUS:
|
||||
case TOKEN_HASH_IDENT:
|
||||
case TOKEN_CT_CONST_IDENT:
|
||||
case TOKEN_CT_IDENT:
|
||||
case TOKEN_STRING:
|
||||
case TOKEN_REAL:
|
||||
|
||||
@@ -304,7 +304,7 @@ Path *parse_path_prefix(Context *context)
|
||||
* | DOUBLE
|
||||
* | TYPE_IDENT
|
||||
* | ident_scope TYPE_IDENT
|
||||
* | TYPE '(' constant_expression ')'
|
||||
* | CT_TYPE_IDENT
|
||||
* ;
|
||||
*
|
||||
* Assume prev_token is the type.
|
||||
@@ -329,18 +329,10 @@ static inline TypeInfo *parse_base_type(Context *context)
|
||||
switch (context->tok.type)
|
||||
{
|
||||
case TOKEN_TYPE_IDENT:
|
||||
case TOKEN_CT_TYPE_IDENT:
|
||||
type_info = type_info_new(TYPE_INFO_IDENTIFIER, context->tok.span);
|
||||
type_info->unresolved.name_loc = context->tok;
|
||||
break;
|
||||
case TOKEN_TYPE:
|
||||
type_info = type_info_new(TYPE_INFO_IDENTIFIER, context->tok.span);
|
||||
advance_and_verify(context, TOKEN_TYPE);
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_type_info);
|
||||
type_info->resolve_status = RESOLVE_NOT_DONE;
|
||||
type_info->unresolved_type_expr = TRY_EXPR_OR(parse_initializer(context), poisoned_type_info);
|
||||
EXPECT_OR(TOKEN_RPAREN, poisoned_type_info);
|
||||
RANGE_EXTEND_PREV(type_info);
|
||||
break;
|
||||
case TOKEN_VOID:
|
||||
type_found = type_void;
|
||||
break;
|
||||
@@ -407,6 +399,9 @@ static inline TypeInfo *parse_base_type(Context *context)
|
||||
case TOKEN_C_ULONGLONG:
|
||||
type_found = type_c_ulonglong;
|
||||
break;
|
||||
case TOKEN_TYPEID:
|
||||
type_found = type_typeid;
|
||||
break;
|
||||
default:
|
||||
SEMA_TOKEN_ERROR(context->tok, "A type name was expected here.");
|
||||
return poisoned_type_info;
|
||||
@@ -463,16 +458,15 @@ static inline TypeInfo *parse_array_type_index(Context *context, TypeInfo *type)
|
||||
}
|
||||
|
||||
/**
|
||||
* type_expression*
|
||||
* type
|
||||
* : base_type
|
||||
* | type_expression '*'
|
||||
* | type_expression '&'
|
||||
* | type_expression array_type_index
|
||||
* | type '*'
|
||||
* | type array_type_index
|
||||
*
|
||||
* Assume already stepped into.
|
||||
* @return Type, poisoned if parsing is invalid.
|
||||
*/
|
||||
TypeInfo *parse_type_expression(Context *context)
|
||||
TypeInfo *parse_type(Context *context)
|
||||
{
|
||||
TypeInfo *type_info = parse_base_type(context);
|
||||
while (type_info_ok(type_info))
|
||||
@@ -548,7 +542,7 @@ Decl *parse_decl(Context *context)
|
||||
bool constant = context->tok.type == TOKEN_CONST;
|
||||
if (local || constant) advance(context);
|
||||
|
||||
TypeInfo *type_info = parse_type_expression(context);
|
||||
TypeInfo *type_info = parse_type(context);
|
||||
TypeInfo *type = TRY_TYPE_OR(type_info, poisoned_decl);
|
||||
|
||||
Decl *decl = TRY_DECL_OR(parse_decl_after_type(context, local, type), poisoned_decl);
|
||||
@@ -582,7 +576,7 @@ static inline Decl *parse_const_declaration(Context *context, Visibility visibil
|
||||
else
|
||||
{
|
||||
if (!consume_const_name(context, "constant")) return poisoned_decl;
|
||||
decl->var.type_info = TRY_TYPE_OR(parse_type_expression(context), poisoned_decl);
|
||||
decl->var.type_info = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
}
|
||||
|
||||
CONSUME_OR(TOKEN_EQ, poisoned_decl);
|
||||
@@ -604,7 +598,7 @@ static inline Decl *parse_const_declaration(Context *context, Visibility visibil
|
||||
*/
|
||||
static inline Decl *parse_global_declaration(Context *context, Visibility visibility)
|
||||
{
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type_expression(context), poisoned_decl);
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
|
||||
Decl *decl = decl_new_var(context->tok, type, VARDECL_GLOBAL, visibility);
|
||||
|
||||
@@ -681,6 +675,21 @@ static inline bool is_expr_after_type_ident(Context *context)
|
||||
return context->next_tok.type == TOKEN_DOT || context->next_tok.type == TOKEN_LPAREN;
|
||||
}
|
||||
|
||||
bool parse_type_or_expr_after_type(Context *context, Expr **expr_ptr, TypeInfo **type_ptr)
|
||||
{
|
||||
if (!type_info_ok(*type_ptr)) return false;
|
||||
if (try_consume(context, TOKEN_DOT))
|
||||
{
|
||||
*expr_ptr = parse_type_access_expr_after_type(context, *type_ptr);
|
||||
*type_ptr = NULL;
|
||||
return expr_ok(*expr_ptr);
|
||||
}
|
||||
if (context->tok.type == TOKEN_LBRACE)
|
||||
{
|
||||
return parse_type_compound_literal_expr_after_type(context, *type_ptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool parse_type_or_expr(Context *context, Expr **expr_ptr, TypeInfo **type_ptr)
|
||||
{
|
||||
switch (context->tok.type)
|
||||
@@ -709,9 +718,10 @@ bool parse_type_or_expr(Context *context, Expr **expr_ptr, TypeInfo **type_ptr)
|
||||
case TOKEN_C_ULONG:
|
||||
case TOKEN_C_ULONGLONG:
|
||||
case TOKEN_TYPE_IDENT:
|
||||
if (context->next_tok.type == TOKEN_DOT || context->next_tok.type == TOKEN_LPAREN) break;
|
||||
*type_ptr = parse_type_expression(context);
|
||||
return type_info_ok(*type_ptr);
|
||||
case TOKEN_CT_TYPE_IDENT:
|
||||
*type_ptr = parse_type(context);
|
||||
return parse_type_or_expr_after_type(context, expr_ptr, type_ptr);
|
||||
return true;
|
||||
case TOKEN_IDENT:
|
||||
if (context->next_tok.type == TOKEN_SCOPE)
|
||||
{
|
||||
@@ -721,35 +731,15 @@ bool parse_type_or_expr(Context *context, Expr **expr_ptr, TypeInfo **type_ptr)
|
||||
{
|
||||
advance(context); advance(context);
|
||||
} while (context->tok.type == TOKEN_IDENT && context->next_tok.type == TOKEN_SCOPE);
|
||||
if (context->tok.type == TOKEN_TYPE_IDENT && !is_expr_after_type_ident(context))
|
||||
if (context->tok.type == TOKEN_TYPE_IDENT)
|
||||
{
|
||||
context_restore_lexer_state(context);
|
||||
*type_ptr = parse_type_expression(context);
|
||||
return type_info_ok(*type_ptr);
|
||||
*type_ptr = parse_type(context);
|
||||
return parse_type_or_expr_after_type(context, expr_ptr, type_ptr);
|
||||
}
|
||||
context_restore_lexer_state(context);
|
||||
}
|
||||
break;
|
||||
case TOKEN_TYPE:
|
||||
{
|
||||
SourceRange start = context->tok.span;
|
||||
advance_and_verify(context, TOKEN_TYPE);
|
||||
CONSUME_OR(TOKEN_LPAREN, false);
|
||||
Expr* inner_expr = NULL;
|
||||
TypeInfo* inner_type = NULL;
|
||||
if (!parse_type_or_expr(context, &inner_expr, &inner_type)) return false;
|
||||
CONSUME_OR(TOKEN_RPAREN, false);
|
||||
if (inner_expr)
|
||||
{
|
||||
*type_ptr = type_info_new(TYPE_INFO_EXPRESSION, inner_expr->span);
|
||||
(**type_ptr).unresolved_type_expr = inner_expr;
|
||||
return true;
|
||||
}
|
||||
Expr *type_expr = expr_new(EXPR_TYPE, start);
|
||||
type_expr->type_expr.type = inner_type;
|
||||
*expr_ptr = parse_precedence_with_left_side(context, type_expr, PREC_ASSIGNMENT);
|
||||
return expr_ok(*expr_ptr);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -877,7 +867,7 @@ static inline bool parse_opt_throw_declaration(Context *context, Visibility visi
|
||||
*/
|
||||
static inline bool parse_param_decl(Context *context, Visibility parent_visibility, Decl*** parameters, bool type_only)
|
||||
{
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type_expression(context), false);
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), false);
|
||||
Decl *param = decl_new_var(context->tok, type, VARDECL_PARAM, parent_visibility);
|
||||
param->span = type->span;
|
||||
if (!try_consume(context, TOKEN_IDENT))
|
||||
@@ -1020,7 +1010,7 @@ bool parse_struct_body(Context *context, Decl *parent, Decl *visible_parent)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type_expression(context), false);
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), false);
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -1116,7 +1106,7 @@ static inline Decl *parse_generics_declaration(Context *context, Visibility visi
|
||||
TypeInfo *rtype = NULL;
|
||||
if (context->tok.type != TOKEN_IDENT)
|
||||
{
|
||||
rtype = TRY_TYPE_OR(parse_type_expression(context), poisoned_decl);
|
||||
rtype = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
}
|
||||
Path *path = parse_path_prefix(context);
|
||||
Decl *decl = decl_new(DECL_GENERIC, context->tok, visibility);
|
||||
@@ -1147,7 +1137,7 @@ static inline Decl *parse_generics_declaration(Context *context, Visibility visi
|
||||
TypeInfo **types = NULL;
|
||||
while (!try_consume(context, TOKEN_COLON))
|
||||
{
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type_expression(context), poisoned_decl);
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
types = VECADD(types, type);
|
||||
if (!try_consume(context, TOKEN_COMMA) && context->tok.type != TOKEN_COLON)
|
||||
{
|
||||
@@ -1258,7 +1248,7 @@ static inline bool parse_func_typedef(Context *context, Decl *decl, Visibility v
|
||||
{
|
||||
decl->typedef_decl.is_func = true;
|
||||
advance_and_verify(context, TOKEN_FUNC);
|
||||
TypeInfo *type_info = TRY_TYPE_OR(parse_type_expression(context), false);
|
||||
TypeInfo *type_info = TRY_TYPE_OR(parse_type(context), false);
|
||||
decl->typedef_decl.function_signature.rtype = type_info;
|
||||
if (!parse_opt_parameter_type_list(context, visibility, &(decl->typedef_decl.function_signature), true))
|
||||
{
|
||||
@@ -1278,7 +1268,7 @@ static inline Decl *parse_typedef_declaration(Context *context, Visibility visib
|
||||
}
|
||||
else
|
||||
{
|
||||
decl->typedef_decl.type_info = TRY_TYPE_OR(parse_type_expression(context), poisoned_decl);
|
||||
decl->typedef_decl.type_info = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
decl->typedef_decl.is_func = false;
|
||||
}
|
||||
CONSUME_OR(TOKEN_AS, poisoned_decl);
|
||||
@@ -1297,7 +1287,7 @@ static inline Decl *parse_macro_declaration(Context *context, Visibility visibil
|
||||
TypeInfo *rtype = NULL;
|
||||
if (context->tok.type != TOKEN_IDENT)
|
||||
{
|
||||
rtype = TRY_TYPE_OR(parse_type_expression(context), poisoned_decl);
|
||||
rtype = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
}
|
||||
|
||||
Decl *decl = decl_new(DECL_MACRO, context->tok, visibility);
|
||||
@@ -1314,7 +1304,6 @@ static inline Decl *parse_macro_declaration(Context *context, Visibility visibil
|
||||
{
|
||||
case TOKEN_IDENT:
|
||||
case TOKEN_CT_IDENT:
|
||||
case TOKEN_HASH_IDENT:
|
||||
break;
|
||||
default:
|
||||
if (parm_type)
|
||||
@@ -1322,7 +1311,7 @@ static inline Decl *parse_macro_declaration(Context *context, Visibility visibil
|
||||
SEMA_TOKEN_ERROR(context->tok, "Expected a macro parameter");
|
||||
return poisoned_decl;
|
||||
}
|
||||
parm_type = TRY_TYPE_OR(parse_type_expression(context), poisoned_decl);
|
||||
parm_type = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
goto TEST_TYPE;
|
||||
}
|
||||
Decl *param = decl_new_var(context->tok, parm_type, VARDECL_PARAM, visibility);
|
||||
@@ -1511,7 +1500,7 @@ static inline Decl *parse_func_definition(Context *context, Visibility visibilit
|
||||
{
|
||||
advance_and_verify(context, TOKEN_FUNC);
|
||||
|
||||
TypeInfo *return_type = TRY_TYPE_OR(parse_type_expression(context), poisoned_decl);
|
||||
TypeInfo *return_type = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
|
||||
Decl *func = decl_new(DECL_FUNC, context->tok, visibility);
|
||||
func->func.function_signature.rtype = return_type;
|
||||
@@ -1695,7 +1684,7 @@ static inline Decl *parse_top_level(Context *context)
|
||||
return parse_error_declaration(context, visibility);
|
||||
case TOKEN_TYPEDEF:
|
||||
return parse_typedef_declaration(context, visibility);
|
||||
case TOKEN_TYPE:
|
||||
case TOKEN_CT_TYPE_IDENT:
|
||||
case TOKEN_TYPE_IDENT:
|
||||
// All of these start type
|
||||
return parse_global_declaration(context, visibility);
|
||||
@@ -1757,7 +1746,6 @@ static inline bool parse_optional_module_params(Context *context, Token **tokens
|
||||
sema_error_range(context->next_tok.span, "Unexpected ','");
|
||||
return false;
|
||||
case TOKEN_CT_IDENT:
|
||||
case TOKEN_HASH_IDENT:
|
||||
case TOKEN_TYPE_IDENT:
|
||||
break;
|
||||
default:
|
||||
@@ -1824,13 +1812,14 @@ static inline void parse_module(Context *context)
|
||||
* : IDENT
|
||||
* | TYPE
|
||||
* | MACRO
|
||||
* | CONST
|
||||
* | CONST_IDENT
|
||||
* ;
|
||||
*
|
||||
* @return true if import succeeded
|
||||
*/
|
||||
static inline bool parse_import_selective(Context *context, Path *path)
|
||||
{
|
||||
// TODO constident, @ etc
|
||||
if (!token_is_symbol(context->tok.type))
|
||||
{
|
||||
SEMA_TOKEN_ERROR(context->tok, "Expected a symbol name here, the syntax is 'import <module> : <symbol>'.");
|
||||
@@ -1981,37 +1970,6 @@ static Expr *parse_type_access(Context *context, TypeInfo *type)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* type_identifier
|
||||
* : TYPE_IDENT initializer_list
|
||||
* | TYPE_IDENT method_ref
|
||||
* ;
|
||||
*
|
||||
* @param left must be null.
|
||||
* @return Expr*
|
||||
*/
|
||||
Expr *parse_type_identifier_with_path(Context *context, Path *path)
|
||||
{
|
||||
TypeInfo *type = type_info_new(TYPE_INFO_IDENTIFIER, path ? path->span : context->tok.span );
|
||||
type->unresolved.path = path;
|
||||
type->unresolved.name_loc = context->tok;
|
||||
advance_and_verify(context, TOKEN_TYPE_IDENT);
|
||||
RANGE_EXTEND_PREV(type);
|
||||
if (context->tok.type == TOKEN_LBRACE)
|
||||
{
|
||||
Expr *expr = expr_new(EXPR_COMPOUND_LITERAL, type->span);
|
||||
expr->expr_compound_literal.type_info = type;
|
||||
expr->expr_compound_literal.initializer = TRY_EXPR_OR(parse_initializer_list(context), poisoned_expr);
|
||||
RANGE_EXTEND_PREV(expr);
|
||||
return expr;
|
||||
}
|
||||
EXPECT_OR(TOKEN_DOT, poisoned_expr);
|
||||
return parse_type_access(context, type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ SEMA_TOKEN_ERROR(context->tok, "Expected ',' or ')'"); return _res; } } while(0)
|
||||
|
||||
Ast *parse_stmt(Context *context);
|
||||
Path *parse_path_prefix(Context *context);
|
||||
Expr *parse_type_identifier_with_path(Context *context, Path *path);
|
||||
Expr *parse_type_expression_with_path(Context *context, Path *path);
|
||||
Expr *parse_expr(Context *context);
|
||||
TypeInfo *parse_type_expression(Context *context);
|
||||
TypeInfo *parse_type(Context *context);
|
||||
Expr* parse_constant_expr(Context *context);
|
||||
Expr *parse_initializer_list(Context *context);
|
||||
Expr *parse_initializer(Context *context);
|
||||
@@ -44,7 +44,8 @@ Expr *parse_expression_list(Context *context);
|
||||
bool parse_type_or_expr(Context *context, Expr **expr_ptr, TypeInfo **type_ptr);
|
||||
Decl *parse_decl_after_type(Context *context, bool local, TypeInfo *type);
|
||||
bool parse_param_list(Context *context, Expr ***result, bool allow_type);
|
||||
|
||||
Expr *parse_type_compound_literal_expr_after_type(Context *context, TypeInfo *type_info);
|
||||
Expr *parse_type_access_expr_after_type(Context *context, TypeInfo *type_info);
|
||||
void error_at_current(Context *context, const char* message, ...);
|
||||
bool try_consume(Context *context, TokenType type);
|
||||
bool consume(Context *context, TokenType type, const char *message, ...);
|
||||
|
||||
@@ -11,6 +11,19 @@
|
||||
* - Disallow jumping in and out of an expression block.
|
||||
*/
|
||||
|
||||
static Expr **expr_copy_expr_list_from_macro(Context *context, Expr *macro, Expr **expr_list);
|
||||
static Expr *expr_copy_from_macro(Context *context, Expr *macro, Expr *source_expr);
|
||||
static Ast *ast_copy_from_macro(Context *context, Expr *macro, Ast *source);
|
||||
static Ast **ast_copy_list_from_macro(Context *context, Expr *macro, Ast **to_copy);
|
||||
|
||||
#define MACRO_COPY_EXPR(x) x = expr_copy_from_macro(context, macro, x)
|
||||
#define MACRO_COPY_TYPE(x) x = type_info_copy_from_macro(context, macro, x)
|
||||
#define MACRO_COPY_TYPE_LIST(x) x = type_info_copy_list_from_macro(context, macro, x)
|
||||
#define MACRO_COPY_EXPR_LIST(x) x = expr_copy_expr_list_from_macro(context, macro, x)
|
||||
#define MACRO_COPY_AST_LIST(x) x = ast_copy_list_from_macro(context, macro, x)
|
||||
#define MACRO_COPY_AST(x) x = ast_copy_from_macro(context, macro, x)
|
||||
|
||||
|
||||
static inline bool is_const(Expr *expr)
|
||||
{
|
||||
return expr->expr_kind == EXPR_CONST;
|
||||
@@ -514,6 +527,14 @@ static inline bool sema_expr_analyse_type_access(Context *context, Type *to, Exp
|
||||
TypeInfo *type_info = expr->type_access.type;
|
||||
if (!sema_resolve_type_info(context, type_info)) return false;
|
||||
Type *canonical = type_info->type->canonical;
|
||||
if (expr->type_access.name.type == TOKEN_TYPEID)
|
||||
{
|
||||
expr->type = type_typeid;
|
||||
expr->expr_kind = EXPR_TYPEID;
|
||||
expr->typeid_expr = type_info;
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
}
|
||||
if (!type_may_have_method_functions(canonical))
|
||||
{
|
||||
SEMA_ERROR(expr, "'%s' does not have method functions.", type_to_error_string(type_info->type));
|
||||
@@ -932,10 +953,7 @@ static inline bool sema_expr_analyse_initializer_list(Context *context, Type *to
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_sizeof(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
TODO
|
||||
}
|
||||
|
||||
|
||||
static inline bool sema_expr_analyse_expr_list(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
@@ -2219,10 +2237,6 @@ static Expr *expr_shallow_copy(Expr *source)
|
||||
}
|
||||
|
||||
|
||||
static Expr **expr_copy_expr_list_from_macro(Context *context, Expr *macro, Expr **expr_list);
|
||||
static Expr *expr_copy_from_macro(Context *context, Expr *macro, Expr *source_expr);
|
||||
static Ast *ast_copy_from_macro(Context *context, Expr *macro, Ast *source);
|
||||
static void ast_copy_list_from_macro(Context *context, Expr *macro, Ast ***to_convert);
|
||||
|
||||
static TypeInfo *type_info_copy_from_macro(Context *context, Expr *macro, TypeInfo *source)
|
||||
{
|
||||
@@ -2259,106 +2273,103 @@ static TypeInfo *type_info_copy_from_macro(Context *context, Expr *macro, TypeIn
|
||||
}
|
||||
|
||||
|
||||
static void ast_copy_list_from_macro(Context *context, Expr *macro, Ast ***to_convert)
|
||||
static Ast** ast_copy_list_from_macro(Context *context, Expr *macro, Ast **to_copy)
|
||||
{
|
||||
Ast **result = NULL;
|
||||
Ast **list = *to_convert;
|
||||
VECEACH(list, i)
|
||||
VECEACH(to_copy, i)
|
||||
{
|
||||
vec_add(result, ast_copy_from_macro(context, macro, list[i]));
|
||||
vec_add(result, ast_copy_from_macro(context, macro, to_copy[i]));
|
||||
}
|
||||
*to_convert = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static Expr *expr_copy_from_macro(Context *context, Expr *macro, Expr *source_expr)
|
||||
{
|
||||
#define EXPR_COPY(x) x = expr_copy_from_macro(context, macro, x)
|
||||
if (!source_expr) return NULL;
|
||||
Expr *expr = expr_shallow_copy(source_expr);
|
||||
switch (source_expr->expr_kind)
|
||||
{
|
||||
case EXPR_TYPEOF:
|
||||
MACRO_COPY_EXPR(expr->typeof_expr);
|
||||
return expr;
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
EXPR_COPY(expr->expr_compound_literal.initializer);
|
||||
expr->expr_compound_literal.type_info = type_info_copy_from_macro(context, macro, expr->expr_compound_literal.type_info);
|
||||
MACRO_COPY_EXPR(expr->expr_compound_literal.initializer);
|
||||
MACRO_COPY_TYPE(expr->expr_compound_literal.type_info);
|
||||
return expr;
|
||||
case EXPR_DESIGNATED_INITIALIZER:
|
||||
// Created during semantic analysis
|
||||
UNREACHABLE
|
||||
case EXPR_RANGE:
|
||||
EXPR_COPY(expr->range_expr.left);
|
||||
EXPR_COPY(expr->range_expr.right);
|
||||
MACRO_COPY_EXPR(expr->range_expr.left);
|
||||
MACRO_COPY_EXPR(expr->range_expr.right);
|
||||
return expr;
|
||||
case EXPR_EXPR_BLOCK:
|
||||
ast_copy_list_from_macro(context, macro, &expr->expr_block.stmts);
|
||||
MACRO_COPY_AST_LIST(expr->expr_block.stmts);
|
||||
return expr;
|
||||
case EXPR_POISONED:
|
||||
return source_expr;
|
||||
case EXPR_TRY:
|
||||
EXPR_COPY(expr->try_expr.expr);
|
||||
EXPR_COPY(expr->try_expr.else_expr);
|
||||
MACRO_COPY_EXPR(expr->try_expr.expr);
|
||||
MACRO_COPY_EXPR(expr->try_expr.else_expr);
|
||||
return expr;
|
||||
case EXPR_CONST:
|
||||
return expr;
|
||||
case EXPR_BINARY:
|
||||
EXPR_COPY(expr->binary_expr.left);
|
||||
EXPR_COPY(expr->binary_expr.right);
|
||||
MACRO_COPY_EXPR(expr->binary_expr.left);
|
||||
MACRO_COPY_EXPR(expr->binary_expr.right);
|
||||
return expr;
|
||||
case EXPR_TERNARY:
|
||||
EXPR_COPY(expr->ternary_expr.cond);
|
||||
EXPR_COPY(expr->ternary_expr.then_expr);
|
||||
EXPR_COPY(expr->ternary_expr.else_expr);
|
||||
MACRO_COPY_EXPR(expr->ternary_expr.cond);
|
||||
MACRO_COPY_EXPR(expr->ternary_expr.then_expr);
|
||||
MACRO_COPY_EXPR(expr->ternary_expr.else_expr);
|
||||
return expr;
|
||||
case EXPR_UNARY:
|
||||
EXPR_COPY(expr->unary_expr.expr);
|
||||
MACRO_COPY_EXPR(expr->unary_expr.expr);
|
||||
return expr;
|
||||
case EXPR_POST_UNARY:
|
||||
EXPR_COPY(expr->post_expr.expr);
|
||||
MACRO_COPY_EXPR(expr->post_expr.expr);
|
||||
return expr;
|
||||
case EXPR_TYPE:
|
||||
expr->type_expr.type = type_info_copy_from_macro(context, macro, expr->type_expr.type);
|
||||
case EXPR_TYPEID:
|
||||
MACRO_COPY_TYPE(expr->typeid_expr);
|
||||
return expr;
|
||||
case EXPR_IDENTIFIER:
|
||||
TODO
|
||||
break;
|
||||
case EXPR_TYPE_ACCESS:
|
||||
expr->type_access.type = type_info_copy_from_macro(context, macro, expr->type_expr.type);
|
||||
MACRO_COPY_TYPE(expr->type_access.type);
|
||||
return expr;
|
||||
case EXPR_CALL:
|
||||
EXPR_COPY(expr->call_expr.function);
|
||||
expr->call_expr.arguments = expr_copy_expr_list_from_macro(context, macro, expr->call_expr.arguments);
|
||||
MACRO_COPY_EXPR(expr->call_expr.function);
|
||||
MACRO_COPY_EXPR_LIST(expr->call_expr.arguments);
|
||||
return expr;
|
||||
case EXPR_SIZEOF:
|
||||
TODO
|
||||
break;
|
||||
case EXPR_SUBSCRIPT:
|
||||
EXPR_COPY(expr->subscript_expr.expr);
|
||||
EXPR_COPY(expr->subscript_expr.index);
|
||||
MACRO_COPY_EXPR(expr->subscript_expr.expr);
|
||||
MACRO_COPY_EXPR(expr->subscript_expr.index);
|
||||
return expr;
|
||||
case EXPR_GROUP:
|
||||
EXPR_COPY(expr->group_expr->group_expr);
|
||||
MACRO_COPY_EXPR(expr->group_expr->group_expr);
|
||||
return expr;
|
||||
case EXPR_ACCESS:
|
||||
EXPR_COPY(expr->access_expr.parent);
|
||||
MACRO_COPY_EXPR(expr->access_expr.parent);
|
||||
return expr;
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
expr->expr_initializer.initializer_expr = expr_copy_expr_list_from_macro(context, macro, expr->expr_initializer.initializer_expr);
|
||||
MACRO_COPY_EXPR_LIST(expr->expr_initializer.initializer_expr);
|
||||
return expr;
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
expr->expression_list = expr_copy_expr_list_from_macro(context, macro, expr->expression_list);
|
||||
MACRO_COPY_EXPR_LIST(expr->expression_list);
|
||||
return expr;
|
||||
case EXPR_CAST:
|
||||
EXPR_COPY(expr->cast_expr.expr);
|
||||
expr->cast_expr.type_info = type_info_copy_from_macro(context, macro, expr->cast_expr.type_info);
|
||||
MACRO_COPY_EXPR(expr->cast_expr.expr);
|
||||
MACRO_COPY_TYPE(expr->cast_expr.type_info);
|
||||
return expr;
|
||||
case EXPR_SCOPED_EXPR:
|
||||
EXPR_COPY(expr->expr_scope.expr);
|
||||
MACRO_COPY_EXPR(expr->expr_scope.expr);
|
||||
return expr;
|
||||
case EXPR_MACRO_EXPR:
|
||||
EXPR_COPY(expr->macro_expr);
|
||||
MACRO_COPY_EXPR(expr->macro_expr);
|
||||
return expr;
|
||||
}
|
||||
#undef EXPR_COPY
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
@@ -2373,21 +2384,18 @@ static Expr **expr_copy_expr_list_from_macro(Context *context, Expr *macro, Expr
|
||||
}
|
||||
|
||||
|
||||
static void type_info_copy_list_from_macro(Context *context, Expr *macro, TypeInfo ***to_convert)
|
||||
static TypeInfo** type_info_copy_list_from_macro(Context *context, Expr *macro, TypeInfo **to_copy)
|
||||
{
|
||||
TypeInfo **result = NULL;
|
||||
TypeInfo **list = *to_convert;
|
||||
VECEACH(list, i)
|
||||
VECEACH(to_copy, i)
|
||||
{
|
||||
vec_add(result, type_info_copy_from_macro(context, macro, list[i]));
|
||||
vec_add(result, type_info_copy_from_macro(context, macro, to_copy[i]));
|
||||
}
|
||||
*to_convert = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
static Ast *ast_copy_from_macro(Context *context, Expr *macro, Ast *source)
|
||||
{
|
||||
#define EXPR_COPY(x) x = expr_copy_from_macro(context, macro, x)
|
||||
#define AST_COPY(x) x = ast_copy_from_macro(context, macro, x)
|
||||
Ast *ast = ast_shallow_copy(source);
|
||||
switch (source->ast_kind)
|
||||
{
|
||||
@@ -2400,87 +2408,87 @@ static Ast *ast_copy_from_macro(Context *context, Expr *macro, Ast *source)
|
||||
case AST_BREAK_STMT:
|
||||
return ast;
|
||||
case AST_CASE_STMT:
|
||||
AST_COPY(ast->case_stmt.body);
|
||||
EXPR_COPY(ast->case_stmt.expr);
|
||||
MACRO_COPY_AST(ast->case_stmt.body);
|
||||
MACRO_COPY_EXPR(ast->case_stmt.expr);
|
||||
return ast;
|
||||
break;
|
||||
case AST_CATCH_STMT:
|
||||
AST_COPY(ast->catch_stmt.body);
|
||||
MACRO_COPY_AST(ast->catch_stmt.body);
|
||||
return ast;
|
||||
case AST_COMPOUND_STMT:
|
||||
ast_copy_list_from_macro(context, macro, &ast->compound_stmt.stmts);
|
||||
MACRO_COPY_AST_LIST(ast->compound_stmt.stmts);
|
||||
return ast;
|
||||
case AST_CONTINUE_STMT:
|
||||
return ast;
|
||||
case AST_CT_IF_STMT:
|
||||
EXPR_COPY(ast->ct_if_stmt.expr);
|
||||
AST_COPY(ast->ct_if_stmt.elif);
|
||||
AST_COPY(ast->ct_if_stmt.then);
|
||||
MACRO_COPY_EXPR(ast->ct_if_stmt.expr);
|
||||
MACRO_COPY_AST(ast->ct_if_stmt.elif);
|
||||
MACRO_COPY_AST(ast->ct_if_stmt.then);
|
||||
return ast;
|
||||
case AST_CT_ELIF_STMT:
|
||||
EXPR_COPY(ast->ct_elif_stmt.expr);
|
||||
AST_COPY(ast->ct_elif_stmt.then);
|
||||
AST_COPY(ast->ct_elif_stmt.elif);
|
||||
MACRO_COPY_EXPR(ast->ct_elif_stmt.expr);
|
||||
MACRO_COPY_AST(ast->ct_elif_stmt.then);
|
||||
MACRO_COPY_AST(ast->ct_elif_stmt.elif);
|
||||
return ast;
|
||||
case AST_CT_ELSE_STMT:
|
||||
AST_COPY(ast->ct_else_stmt);
|
||||
MACRO_COPY_AST(ast->ct_else_stmt);
|
||||
return ast;
|
||||
case AST_CT_FOR_STMT:
|
||||
AST_COPY(ast->ct_for_stmt.body);
|
||||
EXPR_COPY(ast->ct_for_stmt.expr);
|
||||
MACRO_COPY_AST(ast->ct_for_stmt.body);
|
||||
MACRO_COPY_EXPR(ast->ct_for_stmt.expr);
|
||||
return ast;
|
||||
case AST_CT_SWITCH_STMT:
|
||||
EXPR_COPY(ast->ct_switch_stmt.cond);
|
||||
ast_copy_list_from_macro(context, macro, &ast->ct_switch_stmt.body);
|
||||
MACRO_COPY_EXPR(ast->ct_switch_stmt.cond);
|
||||
MACRO_COPY_AST_LIST(ast->ct_switch_stmt.body);
|
||||
return ast;
|
||||
case AST_CT_DEFAULT_STMT:
|
||||
AST_COPY(ast->ct_default_stmt);
|
||||
MACRO_COPY_AST(ast->ct_default_stmt);
|
||||
return ast;
|
||||
case AST_CT_CASE_STMT:
|
||||
AST_COPY(ast->ct_case_stmt.body);
|
||||
type_info_copy_list_from_macro(context, macro, &ast->ct_case_stmt.types);
|
||||
MACRO_COPY_AST(ast->ct_case_stmt.body);
|
||||
MACRO_COPY_TYPE_LIST(ast->ct_case_stmt.types);
|
||||
return ast;
|
||||
case AST_DECLARE_STMT:
|
||||
TODO
|
||||
return ast;
|
||||
case AST_DEFAULT_STMT:
|
||||
AST_COPY(ast->case_stmt.body);
|
||||
MACRO_COPY_AST(ast->case_stmt.body);
|
||||
return ast;
|
||||
case AST_DEFER_STMT:
|
||||
assert(!ast->defer_stmt.prev_defer);
|
||||
AST_COPY(ast->defer_stmt.body);
|
||||
MACRO_COPY_AST(ast->defer_stmt.body);
|
||||
return ast;
|
||||
case AST_DO_STMT:
|
||||
AST_COPY(ast->do_stmt.body);
|
||||
EXPR_COPY(ast->do_stmt.expr);
|
||||
MACRO_COPY_AST(ast->do_stmt.body);
|
||||
MACRO_COPY_EXPR(ast->do_stmt.expr);
|
||||
return ast;
|
||||
case AST_EXPR_STMT:
|
||||
EXPR_COPY(ast->expr_stmt);
|
||||
MACRO_COPY_EXPR(ast->expr_stmt);
|
||||
return ast;
|
||||
case AST_FOR_STMT:
|
||||
EXPR_COPY(ast->for_stmt.cond);
|
||||
EXPR_COPY(ast->for_stmt.incr);
|
||||
AST_COPY(ast->for_stmt.body);
|
||||
AST_COPY(ast->for_stmt.init);
|
||||
MACRO_COPY_EXPR(ast->for_stmt.cond);
|
||||
MACRO_COPY_EXPR(ast->for_stmt.incr);
|
||||
MACRO_COPY_AST(ast->for_stmt.body);
|
||||
MACRO_COPY_AST(ast->for_stmt.init);
|
||||
return ast;
|
||||
case AST_GENERIC_CASE_STMT:
|
||||
AST_COPY(ast->generic_case_stmt.body);
|
||||
MACRO_COPY_AST(ast->generic_case_stmt.body);
|
||||
// ast->generic_case_stmt.types = ...
|
||||
TODO
|
||||
return ast;
|
||||
case AST_GENERIC_DEFAULT_STMT:
|
||||
AST_COPY(ast->generic_default_stmt);
|
||||
MACRO_COPY_AST(ast->generic_default_stmt);
|
||||
return ast;
|
||||
case AST_GOTO_STMT:
|
||||
AST_COPY(ast->goto_stmt.label);
|
||||
MACRO_COPY_AST(ast->goto_stmt.label);
|
||||
// TODO fixup name, which needs to be macro local.
|
||||
TODO
|
||||
return ast;
|
||||
case AST_IF_STMT:
|
||||
AST_COPY(ast->if_stmt.cond);
|
||||
AST_COPY(ast->if_stmt.decl);
|
||||
AST_COPY(ast->if_stmt.else_body);
|
||||
AST_COPY(ast->if_stmt.then_body);
|
||||
MACRO_COPY_AST(ast->if_stmt.cond);
|
||||
MACRO_COPY_AST(ast->if_stmt.decl);
|
||||
MACRO_COPY_AST(ast->if_stmt.else_body);
|
||||
MACRO_COPY_AST(ast->if_stmt.then_body);
|
||||
return ast;
|
||||
case AST_LABEL:
|
||||
assert(!ast->label_stmt.defer);
|
||||
@@ -2491,23 +2499,23 @@ static Ast *ast_copy_from_macro(Context *context, Expr *macro, Ast *source)
|
||||
case AST_NOP_STMT:
|
||||
return ast;
|
||||
case AST_RETURN_STMT:
|
||||
EXPR_COPY(ast->return_stmt.expr);
|
||||
MACRO_COPY_EXPR(ast->return_stmt.expr);
|
||||
// TODO handle conversions?
|
||||
TODO
|
||||
return ast;
|
||||
case AST_DECL_EXPR_LIST:
|
||||
ast_copy_list_from_macro(context, macro, &ast->decl_expr_stmt);
|
||||
MACRO_COPY_AST_LIST(ast->decl_expr_stmt);
|
||||
return ast;
|
||||
case AST_SWITCH_STMT:
|
||||
AST_COPY(ast->switch_stmt.decl);
|
||||
AST_COPY(ast->switch_stmt.cond);
|
||||
ast_copy_list_from_macro(context, macro, &ast->switch_stmt.cases);
|
||||
MACRO_COPY_AST(ast->switch_stmt.decl);
|
||||
MACRO_COPY_AST(ast->switch_stmt.cond);
|
||||
MACRO_COPY_AST_LIST(ast->switch_stmt.cases);
|
||||
return ast;
|
||||
case AST_THROW_STMT:
|
||||
EXPR_COPY(ast->throw_stmt.throw_value);
|
||||
MACRO_COPY_EXPR(ast->throw_stmt.throw_value);
|
||||
return ast;
|
||||
case AST_TRY_STMT:
|
||||
AST_COPY(ast->try_stmt);
|
||||
MACRO_COPY_AST(ast->try_stmt);
|
||||
return ast;
|
||||
case AST_NEXT_STMT:
|
||||
TODO
|
||||
@@ -2516,17 +2524,15 @@ static Ast *ast_copy_from_macro(Context *context, Expr *macro, Ast *source)
|
||||
TODO
|
||||
return ast;
|
||||
case AST_WHILE_STMT:
|
||||
AST_COPY(ast->while_stmt.cond);
|
||||
AST_COPY(ast->while_stmt.decl);
|
||||
AST_COPY(ast->while_stmt.body);
|
||||
MACRO_COPY_AST(ast->while_stmt.cond);
|
||||
MACRO_COPY_AST(ast->while_stmt.decl);
|
||||
MACRO_COPY_AST(ast->while_stmt.body);
|
||||
return ast;
|
||||
case AST_SCOPED_STMT:
|
||||
AST_COPY(ast->scoped_stmt.stmt);
|
||||
MACRO_COPY_AST(ast->scoped_stmt.stmt);
|
||||
return ast;
|
||||
}
|
||||
UNREACHABLE;
|
||||
#undef EXPR_COPY
|
||||
#undef AST_COPY
|
||||
}
|
||||
static inline bool sema_expr_analyse_macro_call(Context *context, Type *to, Expr *macro, Expr *inner)
|
||||
{
|
||||
@@ -2602,11 +2608,11 @@ static inline bool sema_expr_analyse_macro_expr(Context *context, Type *to, Expr
|
||||
|
||||
static inline bool sema_expr_analyse_type(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
if (!sema_resolve_type_info(context, expr->type_expr.type))
|
||||
if (!sema_resolve_type_info(context, expr->typeid_expr))
|
||||
{
|
||||
return expr_poison(expr);
|
||||
}
|
||||
expr->type = type_get_meta(expr->type_expr.type->type);
|
||||
expr->type = type_typeid;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2750,6 +2756,16 @@ static inline bool sema_expr_analyse_compound_literal(Context *context, Type *to
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_typeof(Context *context, Expr *expr)
|
||||
{
|
||||
if (!sema_analyse_expr(context, NULL, expr->typeof_expr)) return false;
|
||||
Type *type = expr->typeof_expr->type->canonical;
|
||||
expr->expr_kind = EXPR_TYPEID;
|
||||
expr->typeid_expr = type_info_new_base(type, expr->typeof_expr->span);
|
||||
expr->type = type_typeid;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
switch (expr->expr_kind)
|
||||
@@ -2761,6 +2777,8 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *
|
||||
UNREACHABLE
|
||||
case EXPR_SCOPED_EXPR:
|
||||
UNREACHABLE
|
||||
case EXPR_TYPEOF:
|
||||
return sema_expr_analyse_typeof(context, expr);
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
return sema_expr_analyse_compound_literal(context, to, expr);
|
||||
case EXPR_EXPR_BLOCK:
|
||||
@@ -2781,7 +2799,7 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *
|
||||
return sema_expr_analyse_unary(context, to, expr);
|
||||
case EXPR_POST_UNARY:
|
||||
return sema_expr_analyse_post_unary(context, to, expr);
|
||||
case EXPR_TYPE:
|
||||
case EXPR_TYPEID:
|
||||
return sema_expr_analyse_type(context, to, expr);
|
||||
case EXPR_IDENTIFIER:
|
||||
return sema_expr_analyse_identifier(context, to, expr);
|
||||
@@ -2789,8 +2807,6 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *
|
||||
return sema_expr_analyse_type_access(context, to, expr);
|
||||
case EXPR_CALL:
|
||||
return sema_expr_analyse_call(context, to, expr);
|
||||
case EXPR_SIZEOF:
|
||||
return sema_expr_analyse_sizeof(context, to, expr);
|
||||
case EXPR_SUBSCRIPT:
|
||||
return sema_expr_analyse_subscript(context, to, expr);
|
||||
case EXPR_GROUP:
|
||||
|
||||
@@ -140,10 +140,12 @@ const char *token_type_to_string(TokenType type)
|
||||
// Identifiers
|
||||
case TOKEN_IDENT:
|
||||
return "IDENT";
|
||||
case TOKEN_HASH_IDENT:
|
||||
return "HASH_IDENT";
|
||||
case TOKEN_CT_IDENT:
|
||||
return "CT_IDENT";
|
||||
case TOKEN_CT_CONST_IDENT:
|
||||
return "CT_CONST_IDENT";
|
||||
case TOKEN_CT_TYPE_IDENT:
|
||||
return "CT_TYPE_IDENT";
|
||||
case TOKEN_CONST_IDENT:
|
||||
return "CONST_IDENT";
|
||||
case TOKEN_TYPE_IDENT:
|
||||
@@ -240,8 +242,10 @@ const char *token_type_to_string(TokenType type)
|
||||
return "true";
|
||||
case TOKEN_TRY:
|
||||
return "try";
|
||||
case TOKEN_TYPE:
|
||||
return "type";
|
||||
case TOKEN_TYPEID:
|
||||
return "typeid";
|
||||
case TOKEN_TYPEOF:
|
||||
return "typeof";
|
||||
case TOKEN_TYPEDEF:
|
||||
return "typedef";
|
||||
case TOKEN_UNION:
|
||||
|
||||
@@ -43,11 +43,9 @@ Type *type_c_uint = &t_cui;
|
||||
Type *type_c_ulong = &t_cul;
|
||||
Type *type_c_ulonglong = &t_cull;
|
||||
|
||||
|
||||
#define META_OFFSET 0
|
||||
#define PTR_OFFSET 1
|
||||
#define VAR_ARRAY_OFFSET 2
|
||||
#define ARRAY_OFFSET 3
|
||||
#define PTR_OFFSET 0
|
||||
#define VAR_ARRAY_OFFSET 1
|
||||
#define ARRAY_OFFSET 2
|
||||
|
||||
Type *type_signed_int_by_bitsize(unsigned bytesize)
|
||||
{
|
||||
@@ -196,8 +194,6 @@ size_t type_size(Type *canonical)
|
||||
case TYPE_POISONED:
|
||||
case TYPE_TYPEDEF:
|
||||
UNREACHABLE;
|
||||
case TYPE_META_TYPE:
|
||||
return 0;
|
||||
case TYPE_ENUM:
|
||||
return canonical->decl->enums.type_info->type->canonical->builtin.bytesize;
|
||||
case TYPE_ERROR:
|
||||
@@ -208,6 +204,7 @@ size_t type_size(Type *canonical)
|
||||
case TYPE_VOID:
|
||||
return 1;
|
||||
case TYPE_BOOL:
|
||||
case TYPE_META_TYPE:
|
||||
case ALL_INTS:
|
||||
case ALL_FLOATS:
|
||||
return canonical->builtin.bytesize;
|
||||
@@ -235,8 +232,6 @@ unsigned int type_abi_alignment(Type *canonical)
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_VOID:
|
||||
UNREACHABLE;
|
||||
case TYPE_META_TYPE:
|
||||
return 0;
|
||||
case TYPE_ENUM:
|
||||
return canonical->decl->enums.type_info->type->canonical->builtin.abi_alignment;
|
||||
case TYPE_ERROR:
|
||||
@@ -244,6 +239,7 @@ unsigned int type_abi_alignment(Type *canonical)
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
return canonical->decl->strukt.abi_alignment;
|
||||
case TYPE_META_TYPE:
|
||||
case TYPE_BOOL:
|
||||
case ALL_INTS:
|
||||
case ALL_FLOATS:
|
||||
@@ -298,31 +294,6 @@ static Type *type_generate_ptr(Type *ptr_type, bool canonical)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static Type *type_generate_meta(Type *type, bool canonical)
|
||||
{
|
||||
if (canonical) type = type->canonical;
|
||||
if (!type->type_cache)
|
||||
{
|
||||
create_type_cache(type);
|
||||
}
|
||||
|
||||
Type *meta = type->type_cache[META_OFFSET];
|
||||
if (meta == NULL)
|
||||
{
|
||||
meta = type_new(TYPE_META_TYPE, strformat("type %s", type->name));
|
||||
meta->child = type;
|
||||
type->type_cache[META_OFFSET] = meta;
|
||||
if (type == type->canonical)
|
||||
{
|
||||
meta->canonical = meta;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta->canonical = type_generate_meta(type->canonical, true);
|
||||
}
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
|
||||
Type *type_get_ptr(Type *ptr_type)
|
||||
@@ -330,11 +301,6 @@ Type *type_get_ptr(Type *ptr_type)
|
||||
return type_generate_ptr(ptr_type, false);
|
||||
}
|
||||
|
||||
Type *type_get_meta(Type *meta_type)
|
||||
{
|
||||
return type_generate_meta(meta_type, false);
|
||||
}
|
||||
|
||||
Type *type_get_indexed_type(Type *type)
|
||||
{
|
||||
switch (type->type_kind)
|
||||
@@ -472,6 +438,7 @@ type_create(#_name, &_shortname, _type, _bits, target->align_ ## _align, target-
|
||||
|
||||
#undef DEF_TYPE
|
||||
|
||||
type_create("typeid", &t_typeid, TYPE_META_TYPE, target->width_pointer, target->align_pref_pointer, target->align_pointer);
|
||||
type_create("void*", &t_voidstar, TYPE_POINTER, target->width_pointer, target->align_pref_pointer, target->align_pointer);
|
||||
create_type_cache(type_void);
|
||||
type_void->type_cache[0] = &t_voidstar;
|
||||
@@ -491,7 +458,6 @@ type_create(#_name, &_shortname, _type, _bits, target->align_ ## _align, target-
|
||||
type_create_alias("c_int", &t_ci, type_signed_int_by_bitsize(target->width_c_int));
|
||||
// TODO fix error size
|
||||
type_create_alias("error", &t_err, type_signed_int_by_bitsize(target->width_c_int));
|
||||
type_create_alias("typeid", &t_typeid, type_signed_int_by_bitsize(target->width_pointer));
|
||||
type_create_alias("c_long", &t_cl, type_signed_int_by_bitsize(target->width_c_long));
|
||||
type_create_alias("c_longlong", &t_cll, type_signed_int_by_bitsize(target->width_c_long_long));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user