Work on getting typeof up and running. Try-else now works.

This commit is contained in:
Christoffer Lerno
2020-04-22 13:53:18 +02:00
parent 8e80091da4
commit 78aa49cc0e
21 changed files with 630 additions and 373 deletions

40
.github/workflows/main2.yml vendored Normal file
View 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

View File

@@ -9,24 +9,25 @@ int yylex(void);
void yyerror(char *s); 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 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 AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_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 XOR_ASSIGN OR_ASSIGN VAR NIL ELVIS HASH_IDENT NEXT
%token AT
%token TYPEDEF MODULE IMPORT %token TYPEDEF MODULE IMPORT
%token CHAR SHORT INT LONG FLOAT DOUBLE CONST VOLATILE VOID %token CHAR SHORT INT LONG FLOAT DOUBLE CONST VOLATILE VOID
%token BYTE USHORT UINT ULONG BOOL %token BYTE USHORT UINT ULONG BOOL
%token TYPEID
%token STRUCT UNION ENUM ELLIPSIS AS LOCAL %token STRUCT UNION ENUM ELLIPSIS AS LOCAL
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN %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 THROWS THROW TRY CATCH SCOPE PUBLIC DEFER ATTRIBUTE IN
%token FN_BLOCK_START FN_BLOCK_END %token FN_BLOCK_START FN_BLOCK_END
%token MULTW ADDW SUBW
%token AUTO %token AUTO
%start translation_unit %start translation_unit
@@ -46,6 +47,7 @@ ident_expression
: CONST_IDENT : CONST_IDENT
| IDENT | IDENT
| CT_IDENT | CT_IDENT
| CT_CONST_IDENT
; ;
primary_expression primary_expression
@@ -55,8 +57,10 @@ primary_expression
| path ident_expression | path ident_expression
| ident_expression | ident_expression
| base_type initializer_list | base_type initializer_list
| base_type '.' IDENT | type '.' IDENT
| TYPE '(' type_expression ')' | type '.' TYPEID
| '(' type ')' '.' IDENT
| '(' type ')' '.' TYPEID
| '(' expression ')' | '(' expression ')'
| FN_BLOCK_START statement_list FN_BLOCK_END | FN_BLOCK_START statement_list FN_BLOCK_END
; ;
@@ -81,7 +85,6 @@ unary_expression
| INC_OP unary_expression | INC_OP unary_expression
| DEC_OP unary_expression | DEC_OP unary_expression
| unary_operator unary_expression | unary_operator unary_expression
| SIZEOF '(' type_expression ')'
; ;
unary_operator unary_operator
@@ -89,7 +92,7 @@ unary_operator
| '*' | '*'
| '+' | '+'
| '-' | '-'
| SUBW | NEG_MOD
| '~' | '~'
| '!' | '!'
| '@' | '@'
@@ -99,7 +102,7 @@ unary_operator
multiplicative_expression multiplicative_expression
: unary_expression : unary_expression
| 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
| multiplicative_expression '%' unary_expression | multiplicative_expression '%' unary_expression
; ;
@@ -120,9 +123,9 @@ bit_expression
additive_expression additive_expression
: bit_expression : 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 '-' bit_expression
| additive_expression SUBW bit_expression | additive_expression SUB_MOD bit_expression
; ;
relational_expression relational_expression
@@ -172,6 +175,9 @@ assignment_operator
| AND_ASSIGN | AND_ASSIGN
| XOR_ASSIGN | XOR_ASSIGN
| OR_ASSIGN | OR_ASSIGN
| MULT_MOD_ASSIGN
| ADD_MOD_ASSIGN
| SUB_MOD_ASSIGN
; ;
constant_expression constant_expression
@@ -201,8 +207,8 @@ identifier_list
macro_argument macro_argument
: CT_IDENT : CT_IDENT
| IDENT | IDENT
| type_expression IDENT | type IDENT
| type_expression CT_IDENT | type CT_IDENT
; ;
macro_argument_list macro_argument_list
@@ -211,20 +217,20 @@ macro_argument_list
; ;
declaration declaration
: type_expression IDENT '=' initializer : type IDENT '=' initializer
| type_expression IDENT | type IDENT
; ;
param_declaration param_declaration
: type_expression : type
| type_expression IDENT | type IDENT
| type_expression IDENT '=' initializer | type IDENT '=' initializer
; ;
parameter_type_list parameter_type_list
: parameter_list : parameter_list
| parameter_list ',' ELLIPSIS | parameter_list ',' ELLIPSIS
| parameter_list ',' type_expression ELLIPSIS | parameter_list ',' type ELLIPSIS
; ;
opt_parameter_type_list opt_parameter_type_list
@@ -253,15 +259,15 @@ base_type
| DOUBLE | DOUBLE
| TYPE_IDENT | TYPE_IDENT
| path TYPE_IDENT | path TYPE_IDENT
| TYPE '(' constant_expression ')' | CT_TYPE_IDENT
; ;
type_expression type
: base_type : base_type
| type_expression '*' | type '*'
| type_expression '[' constant_expression ']' | type '[' constant_expression ']'
| type_expression '[' ']' | type '[' ']'
| type_expression '[' '+' ']' | type '[' '+' ']'
; ;
initializer initializer
@@ -345,7 +351,7 @@ defer_statement
; ;
catch_statement catch_statement
: CATCH '(' type_expression IDENT ')' defer_catch_body : CATCH '(' type IDENT ')' defer_catch_body
| CATCH '(' ERROR IDENT ')' defer_catch_body | CATCH '(' ERROR IDENT ')' defer_catch_body
; ;
@@ -437,8 +443,8 @@ path_ident
; ;
attribute attribute
: AT path_ident : '@' path_ident
| AT path_ident '(' constant_expression ')' | '@' path_ident '(' constant_expression ')'
; ;
attribute_list attribute_list
@@ -479,7 +485,7 @@ func_name
; ;
func_declaration 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 func_definition
@@ -488,7 +494,7 @@ func_definition
; ;
macro_declaration 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 : MACRO IDENT '(' macro_argument_list ')' compound_statement
; ;
@@ -512,13 +518,13 @@ struct_declaration_list
; ;
struct_member_declaration 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 IDENT opt_attributes struct_body
| struct_or_union opt_attributes struct_body | struct_or_union opt_attributes struct_body
; ;
enum_declaration 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 '}' | ENUM TYPE_IDENT opt_attributes '{' enumerator_list '}'
; ;
@@ -537,8 +543,8 @@ error_declaration
; ;
type_list type_list
: type_expression : type
| type_list ',' type_expression | type_list ',' type
; ;
generics_case generics_case
@@ -551,20 +557,20 @@ generics_body
generics_declaration generics_declaration
: GENERIC IDENT '(' macro_argument_list ')' '{' generics_body '}' : 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_declaration
: CONST CT_IDENT '=' initializer ';' : CONST CT_CONST_IDENT '=' initializer ';'
| CONST type_expression IDENT '=' initializer ';' | CONST type CONST_IDENT '=' initializer ';'
; ;
func_typedef func_typedef
: FUNC type_expression opt_parameter_type_list opt_throw_declaration : FUNC type opt_parameter_type_list opt_throw_declaration
; ;
typedef_declaration typedef_declaration
: TYPEDEF type_expression AS TYPE_IDENT ';' : TYPEDEF type AS TYPE_IDENT ';'
| TYPEDEF func_typedef AS TYPE_IDENT ';' | TYPEDEF func_typedef AS TYPE_IDENT ';'
; ;
@@ -590,8 +596,8 @@ attribute_declaration
; ;
global_declaration global_declaration
: type_expression IDENT ';' : type IDENT ';'
| type_expression IDENT '=' initializer ';' | type IDENT '=' initializer ';'
; ;
ct_if ct_if
@@ -640,6 +646,7 @@ module_param
: CT_IDENT : CT_IDENT
| HASH_IDENT | HASH_IDENT
| TYPE_IDENT | TYPE_IDENT
| CT_TYPE_IDENT
| IDENT | IDENT
; ;
@@ -656,12 +663,11 @@ module
specified_import specified_import
: IDENT AS IDENT : IDENT AS IDENT
| IDENT | IDENT
| TYPE | CONST_IDENT
| CONST | '@' IDENT
| MACRO | TYPE_IDENT AS TYPE_IDENT
| TYPE AS TYPE | CONST_IDENT AS CONST_IDENT
| CONST AS CONST | '@' IDENT AS '@' IDENT
| MACRO AS MACRO
; ;
specified_import_list specified_import_list

View 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;
}

View File

@@ -607,24 +607,25 @@ struct WithArray
{ {
int[4] x; int[4] x;
} }
/*
error Err error Err
{ {
TEST_ERR1 TEST_ERR1
} }
*/
/*
func int testThrow(int x) throws Err func int testThrow(int x) throws Err
{ {
if (x < 0) throw Err.TEST_ERR1; if (x < 0) throw Err.TEST_ERR1;
return x * x; return x * x;
} }
*/
func void testErrors() func void testErrors()
{ {
//int x = try testThrow(20) else 0; int x = try testThrow(20) else 1;
int x = 0;
printf("Value was %d, expected 400.\n", x); 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() func void testArray()
@@ -683,9 +684,18 @@ JUMP:
printf("6"); 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) func int main(int x)
{ {
printf("Helo!\n"); printf("Helo!\n");
testErrors(); testErrors();
testDefault(y = 99); testDefault(y = 99);
@@ -695,6 +705,7 @@ func int main(int x)
testAnonStruct(); testAnonStruct();
testSimpleStruct(0); testSimpleStruct(0);
testUnion(); testUnion();
testType();
int efd = 9; int efd = 9;
uint fefoek = 1; uint fefoek = 1;
printf("Helo: %d\n", efd + cast(fefoek, int)); printf("Helo: %d\n", efd + cast(fefoek, int));

View File

@@ -553,10 +553,10 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
fprint_expr_common(file, expr, indent + 1); fprint_expr_common(file, expr, indent + 1);
fprint_expr_recursive(file, expr->access_expr.parent, indent + 1); fprint_expr_recursive(file, expr->access_expr.parent, indent + 1);
break; break;
case EXPR_TYPE: case EXPR_TYPEID:
fprintf_indented(file, indent, "(type\n"); fprintf_indented(file, indent, "(typeid \n");
fprint_expr_common(file, expr, indent + 1); 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; break;
case EXPR_GROUP: case EXPR_GROUP:
fprintf_indented(file, indent, "(group\n"); fprintf_indented(file, indent, "(group\n");

View File

@@ -183,6 +183,7 @@ struct _Type
const char *name; const char *name;
Type **type_cache; Type **type_cache;
void *backend_type; void *backend_type;
void *backend_typeid;
void *backend_debug_type; void *backend_debug_type;
union union
{ {
@@ -438,7 +439,7 @@ typedef struct
Token name; Token name;
Decl *method; Decl *method;
}; };
} ExprTypeRef; } ExprTypeAccess;
typedef struct typedef struct
{ {
@@ -505,11 +506,6 @@ typedef struct
Decl *decl; Decl *decl;
} ExprIdentifier; } ExprIdentifier;
typedef struct
{
TypeInfo *type;
} ExprType;
typedef struct typedef struct
{ {
@@ -575,10 +571,11 @@ struct _Expr
ExprDesignatedInit designated_init_expr; ExprDesignatedInit designated_init_expr;
Expr *group_expr; Expr *group_expr;
ExprCast cast_expr; ExprCast cast_expr;
Expr *typeof_expr;
ExprConst const_expr; ExprConst const_expr;
ExprRange range_expr; ExprRange range_expr;
ExprStructValue struct_value_expr; ExprStructValue struct_value_expr;
ExprTypeRef type_access; ExprTypeAccess type_access;
ExprTry try_expr; ExprTry try_expr;
Expr* macro_expr; Expr* macro_expr;
ExprBinary binary_expr; ExprBinary binary_expr;
@@ -589,7 +586,7 @@ struct _Expr
ExprSubscript subscript_expr; ExprSubscript subscript_expr;
ExprAccess access_expr; ExprAccess access_expr;
ExprIdentifier identifier_expr; ExprIdentifier identifier_expr;
ExprType type_expr; TypeInfo *typeid_expr;
ExprInitializer expr_initializer; ExprInitializer expr_initializer;
ExprCompoundLiteral expr_compound_literal; ExprCompoundLiteral expr_compound_literal;
Expr** expression_list; Expr** expression_list;

View File

@@ -216,17 +216,17 @@ typedef enum
EXPR_TERNARY, EXPR_TERNARY,
EXPR_UNARY, EXPR_UNARY,
EXPR_POST_UNARY, EXPR_POST_UNARY,
EXPR_TYPE, EXPR_TYPEID,
EXPR_IDENTIFIER, EXPR_IDENTIFIER,
EXPR_TYPE_ACCESS, EXPR_TYPE_ACCESS,
EXPR_CALL, EXPR_CALL,
EXPR_GROUP, EXPR_GROUP,
EXPR_SIZEOF,
EXPR_SUBSCRIPT, EXPR_SUBSCRIPT,
EXPR_ACCESS, EXPR_ACCESS,
EXPR_INITIALIZER_LIST, EXPR_INITIALIZER_LIST,
EXPR_EXPRESSION_LIST, EXPR_EXPRESSION_LIST,
EXPR_CAST, EXPR_CAST,
EXPR_TYPEOF,
EXPR_SCOPED_EXPR, EXPR_SCOPED_EXPR,
EXPR_MACRO_EXPR, EXPR_MACRO_EXPR,
EXPR_EXPR_BLOCK, EXPR_EXPR_BLOCK,
@@ -375,6 +375,7 @@ typedef enum
TOKEN_USHORT, TOKEN_USHORT,
TOKEN_USIZE, TOKEN_USIZE,
TOKEN_QUAD, TOKEN_QUAD,
TOKEN_TYPEID,
// C types // C types
TOKEN_C_SHORT, TOKEN_C_SHORT,
@@ -393,10 +394,11 @@ typedef enum
TOKEN_CONST_IDENT, // Any purely upper case ident, TOKEN_CONST_IDENT, // Any purely upper case ident,
TOKEN_TYPE_IDENT, // Any ident on the format FooBar or __FooBar 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. // Otherwise we allow things like "# foo" which would be pretty bad.
TOKEN_HASH_IDENT, // #foobar
TOKEN_CT_IDENT, // $foobar TOKEN_CT_IDENT, // $foobar
TOKEN_CT_CONST_IDENT, // $FOOBAR
TOKEN_CT_TYPE_IDENT, // $Foobar
TOKEN_STRING, // "Teststring" TOKEN_STRING, // "Teststring"
TOKEN_INTEGER, // 123 0x23 0b10010 0o327 TOKEN_INTEGER, // 123 0x23 0b10010 0o327
@@ -444,13 +446,13 @@ typedef enum
TOKEN_THROWS, TOKEN_THROWS,
TOKEN_TRUE, TOKEN_TRUE,
TOKEN_TRY, TOKEN_TRY,
TOKEN_TYPE, // Reserved
TOKEN_TYPEDEF, TOKEN_TYPEDEF,
TOKEN_UNION, TOKEN_UNION,
TOKEN_UNTIL, TOKEN_UNTIL,
TOKEN_VAR, // Reserved TOKEN_VAR, // Reserved
TOKEN_VOLATILE, TOKEN_VOLATILE,
TOKEN_WHILE, TOKEN_WHILE,
TOKEN_TYPEOF,
TOKEN_CT_CASE, // $case TOKEN_CT_CASE, // $case
TOKEN_CT_DEFAULT, // $default TOKEN_CT_DEFAULT, // $default

View File

@@ -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 // Parses identifiers. Note that this is a bit complicated here since
// we split identifiers into 2 types + find keywords. // 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; TokenType type = 0;
uint32_t hash = FNV1_SEED; uint32_t hash = FNV1_SEED;
if (prefix)
{
hash = FNV1a(prefix, hash);
}
while (peek(lexer) == '_') while (peek(lexer) == '_')
{ {
hash = FNV1a(next(lexer), hash); hash = FNV1a(next(lexer), hash);
@@ -261,11 +264,11 @@ static inline Token scan_ident(Lexer *lexer)
case 'z': case 'z':
if (!type) 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; break;
case 'A': case 'B': case 'C': case 'D': case 'E': 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 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'U': case 'V': case 'W': case 'X': case 'Y':
case 'Z': case 'Z':
if (!type) type = TOKEN_CONST_IDENT; if (!type) type = const_token;
break; break;
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': 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); hash = FNV1a(next(lexer), hash);
} }
// Allow bang!
if (peek(lexer) == '!' && type == normal)
{
hash = FNV1a(next(lexer), hash);
}
EXIT:; EXIT:;
uint32_t len = lexer->current - lexer->lexing_start; uint32_t len = lexer->current - lexer->lexing_start;
const char* interned_string = symtab_add(lexer->lexing_start, len, hash, &type); const char* interned_string = symtab_add(lexer->lexing_start, len, hash, &type);
@@ -485,9 +493,9 @@ Token lexer_scan_token(Lexer *lexer)
case '"': case '"':
return scan_string(lexer); return scan_string(lexer);
case '#': case '#':
return scan_prefixed_ident(lexer, TOKEN_HASH_IDENT, TOKEN_HASH, false, "#"); return make_token(lexer, TOKEN_HASH, "#");
case '$': 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 ',': case ',':
return make_token(lexer, TOKEN_COMMA, ","); return make_token(lexer, TOKEN_COMMA, ",");
case ';': case ';':
@@ -556,7 +564,7 @@ Token lexer_scan_token(Lexer *lexer)
if (is_alphanum_(c)) if (is_alphanum_(c))
{ {
backtrack(lexer); 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) if (c < 0)
{ {
@@ -610,12 +618,7 @@ Token lexer_scan_ident_test(Lexer *lexer, const char *scan)
if (scan[0] == '$') if (scan[0] == '$')
{ {
next(lexer); 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] == '#') return scan_ident(lexer, TOKEN_IDENT, TOKEN_CONST_IDENT, TOKEN_TYPE_IDENT, 0);
{
next(lexer);
return scan_prefixed_ident(lexer, TOKEN_HASH_IDENT, TOKEN_HASH, false, "#");
}
return scan_ident(lexer);
} }

View File

@@ -254,6 +254,73 @@ void llvm_codegen_setup()
intrinsics_setup = true; 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) void llvm_codegen(Context *context)
{ {
assert(intrinsics_setup); assert(intrinsics_setup);
@@ -269,6 +336,10 @@ void llvm_codegen(Context *context)
{ {
gencontext_emit_function_decl(&gen_context, context->functions[i]); 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) VECEACH(context->functions, i)
{ {
Decl *decl = context->functions[i]; Decl *decl = context->functions[i];

View File

@@ -6,6 +6,15 @@
#include "compiler_internal.h" #include "compiler_internal.h"
#include "bigint.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) static inline LLVMValueRef gencontext_emit_add_int(GenContext *context, Type *type, bool use_mod, LLVMValueRef left, LLVMValueRef right)
{ {
if (use_mod) if (use_mod)
@@ -88,7 +97,7 @@ static inline LLVMValueRef gencontext_emit_subscript_addr(GenContext *context, E
case TYPE_ARRAY: case TYPE_ARRAY:
{ {
// TODO insert trap on overflow. // TODO insert trap on overflow.
LLVMValueRef zero = LLVMConstInt(llvm_type(type_int), 0, false); LLVMValueRef zero = llvm_int(type_int, 0);
LLVMValueRef indices[2] = { LLVMValueRef indices[2] = {
zero, zero,
index_value, index_value,
@@ -172,6 +181,7 @@ LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
case EXPR_DESIGNATED_INITIALIZER: case EXPR_DESIGNATED_INITIALIZER:
// Should only appear when generating designated initializers. // Should only appear when generating designated initializers.
UNREACHABLE UNREACHABLE
case EXPR_IDENTIFIER: case EXPR_IDENTIFIER:
return expr->identifier_expr.decl->var.backend_ref; return expr->identifier_expr.decl->var.backend_ref;
case EXPR_UNARY: case EXPR_UNARY:
@@ -188,10 +198,9 @@ LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
case EXPR_GROUP: case EXPR_GROUP:
return gencontext_emit_address(context, expr->group_expr); return gencontext_emit_address(context, expr->group_expr);
case EXPR_CONST: case EXPR_CONST:
case EXPR_TYPE: case EXPR_TYPEID:
case EXPR_POISONED: case EXPR_POISONED:
case EXPR_TRY: case EXPR_TRY:
case EXPR_SIZEOF:
case EXPR_BINARY: case EXPR_BINARY:
case EXPR_TERNARY: case EXPR_TERNARY:
case EXPR_POST_UNARY: case EXPR_POST_UNARY:
@@ -201,6 +210,7 @@ LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
case EXPR_EXPRESSION_LIST: case EXPR_EXPRESSION_LIST:
case EXPR_CAST: case EXPR_CAST:
case EXPR_MACRO_EXPR: case EXPR_MACRO_EXPR:
case EXPR_TYPEOF:
UNREACHABLE UNREACHABLE
} }
UNREACHABLE UNREACHABLE
@@ -345,7 +355,7 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr_addr(GenContext
case DESIGNATED_SUBSCRIPT: case DESIGNATED_SUBSCRIPT:
{ {
// TODO range, more arrays // 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 index = gencontext_emit_expr(context, path->index_expr);
LLVMValueRef indices[2] = { LLVMValueRef indices[2] = {
zero, zero,
@@ -418,7 +428,8 @@ LLVMValueRef gencontext_emit_unary_expr(GenContext *context, Expr *expr)
case UNARYOP_ERROR: case UNARYOP_ERROR:
FATAL_ERROR("Illegal unary op %s", expr->unary_expr.operator); FATAL_ERROR("Illegal unary op %s", expr->unary_expr.operator);
case UNARYOP_NOT: 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: case UNARYOP_BITNEG:
return LLVMBuildNot(context->builder, gencontext_emit_expr(context, expr->unary_expr.expr), "bnot"); return LLVMBuildNot(context->builder, gencontext_emit_expr(context, expr->unary_expr.expr), "bnot");
case UNARYOP_NEGMOD: case UNARYOP_NEGMOD:
@@ -431,7 +442,7 @@ LLVMValueRef gencontext_emit_unary_expr(GenContext *context, Expr *expr)
assert(!type_is_unsigned(type)); assert(!type_is_unsigned(type));
{ {
LLVMValueRef to_negate = gencontext_emit_expr(context, expr->unary_expr.expr); 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) if (build_options.debug_mode)
{ {
LLVMTypeRef type_to_use = llvm_type(type->canonical); 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"); LLVMValueRef phi = LLVMBuildPhi(context->builder, llvm_type(type_bool), "val");
// Simplify for LLVM by entering the constants we already know of. // 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 }; LLVMValueRef logic_values[2] = { result_on_skip, rhs };
LLVMBasicBlockRef blocks[2] = { start_block, rhs_block }; LLVMBasicBlockRef blocks[2] = { start_block, rhs_block };
LLVMAddIncoming(phi, logic_values, blocks, 2); 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; if (rhs_signed) return comp_value;
// Otherwise, special handling for left side signed, right side unsigned. // 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) switch (binary_op)
{ {
case BINARYOP_EQ: 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); 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) LLVMValueRef gencontext_emit_try_expr(GenContext *context, Expr *expr)
{ {
if (expr->try_expr.else_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) 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) switch (expr->const_expr.kind)
{ {
case ALL_INTS: 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 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: case ALL_FLOATS:
return LLVMConstReal(type, (double) expr->const_expr.f); return LLVMConstReal(llvm_type(type), (double) expr->const_expr.f);
case TYPE_POINTER: case TYPE_POINTER:
return LLVMConstNull(type); return LLVMConstNull(llvm_type(type));
case TYPE_BOOL: 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: 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); LLVMSetLinkage(global_name, LLVMInternalLinkage);
LLVMSetGlobalConstant(global_name, 1); LLVMSetGlobalConstant(global_name, 1);
LLVMSetInitializer(global_name, LLVMConstStringInContext(context->context, 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; size_t catch_index = context->catch_stack_index;
while (catch_index > 0) 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]; Catch *current_catch = &context->catch_stack[catch_index];
if (!current_catch->decl) 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); gencontext_emit_block(context, after_block);
return; 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); LLVMValueRef maybe_error = gencontext_emit_load(context, type_error_union, error_param);
TODO // Incorrect, must get subset if this is 128 bits 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 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. // 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); return gencontext_emit_post_unary_expr(context, expr);
case EXPR_TRY: case EXPR_TRY:
return gencontext_emit_try_expr(context, expr); return gencontext_emit_try_expr(context, expr);
case EXPR_TYPE: case EXPR_TYPEID:
case EXPR_SIZEOF: return gencontext_emit_typeid(context, expr);
case EXPR_TYPE_ACCESS: case EXPR_TYPE_ACCESS:
case EXPR_MACRO_EXPR: case EXPR_MACRO_EXPR:
case EXPR_TYPEOF:
// These are folded in the semantic analysis step. // These are folded in the semantic analysis step.
UNREACHABLE UNREACHABLE
case EXPR_IDENTIFIER: case EXPR_IDENTIFIER:

View File

@@ -231,6 +231,8 @@ void gencontext_emit_function_decl(GenContext *context, Decl *decl)
} }
} }
void gencontext_emit_extern_decl(GenContext *context, Decl *decl) void gencontext_emit_extern_decl(GenContext *context, Decl *decl)
{ {
switch (decl->decl_kind) switch (decl->decl_kind)
@@ -253,6 +255,7 @@ void gencontext_emit_extern_decl(GenContext *context, Decl *decl)
case DECL_STRUCT: case DECL_STRUCT:
case DECL_UNION: case DECL_UNION:
llvm_type(decl->type); llvm_type(decl->type);
TODO // Fix typeid
break; break;
case DECL_ENUM: case DECL_ENUM:
TODO TODO

View File

@@ -76,6 +76,7 @@ typedef struct
LLVMBasicBlockRef expr_block_exit; LLVMBasicBlockRef expr_block_exit;
bool current_block_is_target : 1; bool current_block_is_target : 1;
bool did_call_stack_save : 1; bool did_call_stack_save : 1;
LLVMTypeRef type_data_definitions[TYPE_KINDS];
} GenContext; } GenContext;
extern unsigned sadd_overflow_intrinsic_id; extern unsigned sadd_overflow_intrinsic_id;

View File

@@ -10,6 +10,8 @@ static inline LLVMTypeRef gencontext_create_basic_llvm_type(GenContext *context,
{ {
switch (type->type_kind) switch (type->type_kind)
{ {
case TYPE_META_TYPE:
return LLVMIntTypeInContext(context->context, type->builtin.bitsize);
case TYPE_BOOL: case TYPE_BOOL:
return LLVMInt1TypeInContext(context->context); return LLVMInt1TypeInContext(context->context);
case TYPE_I8: case TYPE_I8:

View File

@@ -167,9 +167,10 @@ LLVMTypeRef llvm_get_type(LLVMContextRef context, Type *type)
switch (type->type_kind) switch (type->type_kind)
{ {
case TYPE_POISONED: case TYPE_POISONED:
case TYPE_META_TYPE:
case TYPE_ERROR: case TYPE_ERROR:
UNREACHABLE; UNREACHABLE;
case TYPE_META_TYPE:
return type->backend_type = LLVMIntTypeInContext(context, type->builtin.bitsize);
case TYPE_TYPEDEF: case TYPE_TYPEDEF:
return type->backend_type = llvm_get_type(context, type->canonical); return type->backend_type = llvm_get_type(context, type->canonical);
case TYPE_ENUM: case TYPE_ENUM:

View File

@@ -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."); sema_error_range(start, "Did not expect a type here, only expressions.");
return false; return false;
} }
expr = expr_new(EXPR_TYPE, start); expr = expr_new(EXPR_TYPEID, type->span);
RANGE_EXTEND_PREV(expr); RANGE_EXTEND_PREV(expr);
expr->type_expr.type = type;
} }
vec_add(*result, expr); vec_add(*result, expr);
if (!try_consume(context, TOKEN_COMMA)) 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) static Expr *parse_type_identifier(Context *context, Expr *left)
{ {
assert(!left && "Unexpected left hand side"); 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) 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); CONSUME_OR(TOKEN_LPAREN, poisoned_expr);
expr->cast_expr.expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr); expr->cast_expr.expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
CONSUME_OR(TOKEN_COMMA, 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); CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
return expr; return expr;
} }
@@ -365,17 +374,6 @@ static Expr *parse_identifier(Context *context, Expr *left)
return parse_identifier_with_path(context, NULL); 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) 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: case TOKEN_CONST_IDENT:
return parse_identifier_with_path(context, path); return parse_identifier_with_path(context, path);
case TOKEN_TYPE_IDENT: case TOKEN_TYPE_IDENT:
return parse_type_identifier_with_path(context, path); return parse_type_expression_with_path(context, path);
default: default:
SEMA_TOKEN_ERROR(context->tok, "Expected a type, function or constant."); SEMA_TOKEN_ERROR(context->tok, "Expected a type, function or constant.");
return poisoned_expr; return poisoned_expr;
@@ -721,6 +719,63 @@ static Expr *parse_nil(Context *context, Expr *left)
return number; 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 * function_block
* : '({' stmt_list '})' * : '({' stmt_list '})'
@@ -746,10 +801,9 @@ ParseRule rules[TOKEN_EOF + 1] = {
[TOKEN_MINUSMINUS] = { parse_unary_expr, parse_post_unary, PREC_CALL }, [TOKEN_MINUSMINUS] = { parse_unary_expr, parse_post_unary, PREC_CALL },
[TOKEN_LPAREN] = { parse_grouping_expr, parse_call_expr, PREC_CALL }, [TOKEN_LPAREN] = { parse_grouping_expr, parse_call_expr, PREC_CALL },
[TOKEN_LPARBRA] = { parse_expr_block, NULL, PREC_NONE }, [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_CAST] = { parse_cast_expr, NULL, PREC_NONE },
[TOKEN_TYPEOF] = { parse_typeof_expr, NULL, PREC_NONE },
[TOKEN_TRY] = { parse_try_expr, NULL, PREC_TRY }, [TOKEN_TRY] = { parse_try_expr, NULL, PREC_TRY },
//[TOKEN_SIZEOF] = { parse_sizeof, NULL, PREC_NONE },
[TOKEN_LBRACKET] = { NULL, parse_subscript_expr, PREC_CALL }, [TOKEN_LBRACKET] = { NULL, parse_subscript_expr, PREC_CALL },
[TOKEN_MINUS] = { parse_unary_expr, parse_binary, PREC_ADDITIVE }, [TOKEN_MINUS] = { parse_unary_expr, parse_binary, PREC_ADDITIVE },
[TOKEN_MINUS_MOD] = { parse_unary_expr, parse_binary, PREC_ADDITIVE }, [TOKEN_MINUS_MOD] = { parse_unary_expr, parse_binary, PREC_ADDITIVE },

View File

@@ -91,7 +91,7 @@ static inline Ast* parse_catch_stmt(Context *context)
TypeInfo *type = NULL; TypeInfo *type = NULL;
if (!try_consume(context, TOKEN_ERROR_TYPE)) 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); EXPECT_IDENT_FOR_OR("error parameter", poisoned_ast);
Decl *decl = decl_new_var(context->tok, type, VARDECL_PARAM, VISIBLE_LOCAL); 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); advance(context);
while (1) 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); vec_add(stmt->ct_case_stmt.types, type);
if (!try_consume(context, TOKEN_COMMA)) break; if (!try_consume(context, TOKEN_COMMA)) break;
} }
@@ -632,17 +632,19 @@ Ast *parse_stmt(Context *context)
case TOKEN_C_UINT: case TOKEN_C_UINT:
case TOKEN_C_ULONG: case TOKEN_C_ULONG:
case TOKEN_C_ULONGLONG: case TOKEN_C_ULONGLONG:
case TOKEN_TYPEID:
case TOKEN_CT_TYPE_IDENT:
case TOKEN_TYPE_IDENT: case TOKEN_TYPE_IDENT:
if (context->next_tok.type == TOKEN_DOT || context->next_tok.type == TOKEN_LBRACE) if (context->next_tok.type == TOKEN_DOT || context->next_tok.type == TOKEN_LBRACE)
{ {
return parse_expr_stmt(context); return parse_expr_stmt(context);
} }
return parse_declaration_stmt(context); return parse_declaration_stmt(context);
case TOKEN_TYPEOF:
TODO
case TOKEN_LOCAL: // Local means declaration! case TOKEN_LOCAL: // Local means declaration!
case TOKEN_CONST: // Const means declaration! case TOKEN_CONST: // Const means declaration!
return parse_declaration_stmt(context); return parse_declaration_stmt(context);
case TOKEN_TYPE:
return parse_decl_or_expr_stmt(context);
case TOKEN_CONST_IDENT: case TOKEN_CONST_IDENT:
if (context->next_tok.type == TOKEN_COLON) if (context->next_tok.type == TOKEN_COLON)
{ {
@@ -725,7 +727,7 @@ Ast *parse_stmt(Context *context)
case TOKEN_PLUS: case TOKEN_PLUS:
case TOKEN_MINUSMINUS: case TOKEN_MINUSMINUS:
case TOKEN_PLUSPLUS: case TOKEN_PLUSPLUS:
case TOKEN_HASH_IDENT: case TOKEN_CT_CONST_IDENT:
case TOKEN_CT_IDENT: case TOKEN_CT_IDENT:
case TOKEN_STRING: case TOKEN_STRING:
case TOKEN_REAL: case TOKEN_REAL:

View File

@@ -304,7 +304,7 @@ Path *parse_path_prefix(Context *context)
* | DOUBLE * | DOUBLE
* | TYPE_IDENT * | TYPE_IDENT
* | ident_scope TYPE_IDENT * | ident_scope TYPE_IDENT
* | TYPE '(' constant_expression ')' * | CT_TYPE_IDENT
* ; * ;
* *
* Assume prev_token is the type. * Assume prev_token is the type.
@@ -329,18 +329,10 @@ static inline TypeInfo *parse_base_type(Context *context)
switch (context->tok.type) switch (context->tok.type)
{ {
case TOKEN_TYPE_IDENT: case TOKEN_TYPE_IDENT:
case TOKEN_CT_TYPE_IDENT:
type_info = type_info_new(TYPE_INFO_IDENTIFIER, context->tok.span); type_info = type_info_new(TYPE_INFO_IDENTIFIER, context->tok.span);
type_info->unresolved.name_loc = context->tok; type_info->unresolved.name_loc = context->tok;
break; 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: case TOKEN_VOID:
type_found = type_void; type_found = type_void;
break; break;
@@ -407,6 +399,9 @@ static inline TypeInfo *parse_base_type(Context *context)
case TOKEN_C_ULONGLONG: case TOKEN_C_ULONGLONG:
type_found = type_c_ulonglong; type_found = type_c_ulonglong;
break; break;
case TOKEN_TYPEID:
type_found = type_typeid;
break;
default: default:
SEMA_TOKEN_ERROR(context->tok, "A type name was expected here."); SEMA_TOKEN_ERROR(context->tok, "A type name was expected here.");
return poisoned_type_info; return poisoned_type_info;
@@ -463,16 +458,15 @@ static inline TypeInfo *parse_array_type_index(Context *context, TypeInfo *type)
} }
/** /**
* type_expression* * type
* : base_type * : base_type
* | type_expression '*' * | type '*'
* | type_expression '&' * | type array_type_index
* | type_expression array_type_index
* *
* Assume already stepped into. * Assume already stepped into.
* @return Type, poisoned if parsing is invalid. * @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); TypeInfo *type_info = parse_base_type(context);
while (type_info_ok(type_info)) while (type_info_ok(type_info))
@@ -548,7 +542,7 @@ Decl *parse_decl(Context *context)
bool constant = context->tok.type == TOKEN_CONST; bool constant = context->tok.type == TOKEN_CONST;
if (local || constant) advance(context); 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); TypeInfo *type = TRY_TYPE_OR(type_info, poisoned_decl);
Decl *decl = TRY_DECL_OR(parse_decl_after_type(context, local, type), 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 else
{ {
if (!consume_const_name(context, "constant")) return poisoned_decl; 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); 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) 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); 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; 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) bool parse_type_or_expr(Context *context, Expr **expr_ptr, TypeInfo **type_ptr)
{ {
switch (context->tok.type) 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_ULONG:
case TOKEN_C_ULONGLONG: case TOKEN_C_ULONGLONG:
case TOKEN_TYPE_IDENT: case TOKEN_TYPE_IDENT:
if (context->next_tok.type == TOKEN_DOT || context->next_tok.type == TOKEN_LPAREN) break; case TOKEN_CT_TYPE_IDENT:
*type_ptr = parse_type_expression(context); *type_ptr = parse_type(context);
return type_info_ok(*type_ptr); return parse_type_or_expr_after_type(context, expr_ptr, type_ptr);
return true;
case TOKEN_IDENT: case TOKEN_IDENT:
if (context->next_tok.type == TOKEN_SCOPE) 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); advance(context); advance(context);
} while (context->tok.type == TOKEN_IDENT && context->next_tok.type == TOKEN_SCOPE); } 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); context_restore_lexer_state(context);
*type_ptr = parse_type_expression(context); *type_ptr = parse_type(context);
return type_info_ok(*type_ptr); return parse_type_or_expr_after_type(context, expr_ptr, type_ptr);
} }
context_restore_lexer_state(context); context_restore_lexer_state(context);
} }
break; 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: default:
break; 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) 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); Decl *param = decl_new_var(context->tok, type, VARDECL_PARAM, parent_visibility);
param->span = type->span; param->span = type->span;
if (!try_consume(context, TOKEN_IDENT)) if (!try_consume(context, TOKEN_IDENT))
@@ -1020,7 +1010,7 @@ bool parse_struct_body(Context *context, Decl *parent, Decl *visible_parent)
} }
continue; continue;
} }
TypeInfo *type = TRY_TYPE_OR(parse_type_expression(context), false); TypeInfo *type = TRY_TYPE_OR(parse_type(context), false);
while (1) while (1)
{ {
@@ -1116,7 +1106,7 @@ static inline Decl *parse_generics_declaration(Context *context, Visibility visi
TypeInfo *rtype = NULL; TypeInfo *rtype = NULL;
if (context->tok.type != TOKEN_IDENT) 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); Path *path = parse_path_prefix(context);
Decl *decl = decl_new(DECL_GENERIC, context->tok, visibility); 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; TypeInfo **types = NULL;
while (!try_consume(context, TOKEN_COLON)) 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); types = VECADD(types, type);
if (!try_consume(context, TOKEN_COMMA) && context->tok.type != TOKEN_COLON) 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; decl->typedef_decl.is_func = true;
advance_and_verify(context, TOKEN_FUNC); 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; decl->typedef_decl.function_signature.rtype = type_info;
if (!parse_opt_parameter_type_list(context, visibility, &(decl->typedef_decl.function_signature), true)) 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 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; decl->typedef_decl.is_func = false;
} }
CONSUME_OR(TOKEN_AS, poisoned_decl); CONSUME_OR(TOKEN_AS, poisoned_decl);
@@ -1297,7 +1287,7 @@ static inline Decl *parse_macro_declaration(Context *context, Visibility visibil
TypeInfo *rtype = NULL; TypeInfo *rtype = NULL;
if (context->tok.type != TOKEN_IDENT) 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); 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_IDENT:
case TOKEN_CT_IDENT: case TOKEN_CT_IDENT:
case TOKEN_HASH_IDENT:
break; break;
default: default:
if (parm_type) 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"); SEMA_TOKEN_ERROR(context->tok, "Expected a macro parameter");
return poisoned_decl; 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; goto TEST_TYPE;
} }
Decl *param = decl_new_var(context->tok, parm_type, VARDECL_PARAM, visibility); 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); 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); Decl *func = decl_new(DECL_FUNC, context->tok, visibility);
func->func.function_signature.rtype = return_type; 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); return parse_error_declaration(context, visibility);
case TOKEN_TYPEDEF: case TOKEN_TYPEDEF:
return parse_typedef_declaration(context, visibility); return parse_typedef_declaration(context, visibility);
case TOKEN_TYPE: case TOKEN_CT_TYPE_IDENT:
case TOKEN_TYPE_IDENT: case TOKEN_TYPE_IDENT:
// All of these start type // All of these start type
return parse_global_declaration(context, visibility); 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 ','"); sema_error_range(context->next_tok.span, "Unexpected ','");
return false; return false;
case TOKEN_CT_IDENT: case TOKEN_CT_IDENT:
case TOKEN_HASH_IDENT:
case TOKEN_TYPE_IDENT: case TOKEN_TYPE_IDENT:
break; break;
default: default:
@@ -1824,13 +1812,14 @@ static inline void parse_module(Context *context)
* : IDENT * : IDENT
* | TYPE * | TYPE
* | MACRO * | MACRO
* | CONST * | CONST_IDENT
* ; * ;
* *
* @return true if import succeeded * @return true if import succeeded
*/ */
static inline bool parse_import_selective(Context *context, Path *path) static inline bool parse_import_selective(Context *context, Path *path)
{ {
// TODO constident, @ etc
if (!token_is_symbol(context->tok.type)) if (!token_is_symbol(context->tok.type))
{ {
SEMA_TOKEN_ERROR(context->tok, "Expected a symbol name here, the syntax is 'import <module> : <symbol>'."); 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);
}

View File

@@ -31,9 +31,9 @@ SEMA_TOKEN_ERROR(context->tok, "Expected ',' or ')'"); return _res; } } while(0)
Ast *parse_stmt(Context *context); Ast *parse_stmt(Context *context);
Path *parse_path_prefix(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); Expr *parse_expr(Context *context);
TypeInfo *parse_type_expression(Context *context); TypeInfo *parse_type(Context *context);
Expr* parse_constant_expr(Context *context); Expr* parse_constant_expr(Context *context);
Expr *parse_initializer_list(Context *context); Expr *parse_initializer_list(Context *context);
Expr *parse_initializer(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); bool parse_type_or_expr(Context *context, Expr **expr_ptr, TypeInfo **type_ptr);
Decl *parse_decl_after_type(Context *context, bool local, TypeInfo *type); Decl *parse_decl_after_type(Context *context, bool local, TypeInfo *type);
bool parse_param_list(Context *context, Expr ***result, bool allow_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, ...); void error_at_current(Context *context, const char* message, ...);
bool try_consume(Context *context, TokenType type); bool try_consume(Context *context, TokenType type);
bool consume(Context *context, TokenType type, const char *message, ...); bool consume(Context *context, TokenType type, const char *message, ...);

View File

@@ -11,6 +11,19 @@
* - Disallow jumping in and out of an expression block. * - 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) static inline bool is_const(Expr *expr)
{ {
return expr->expr_kind == EXPR_CONST; 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; TypeInfo *type_info = expr->type_access.type;
if (!sema_resolve_type_info(context, type_info)) return false; if (!sema_resolve_type_info(context, type_info)) return false;
Type *canonical = type_info->type->canonical; 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)) if (!type_may_have_method_functions(canonical))
{ {
SEMA_ERROR(expr, "'%s' does not have method functions.", type_to_error_string(type_info->type)); 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; 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) 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) 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 **result = NULL;
Ast **list = *to_convert; VECEACH(to_copy, i)
VECEACH(list, 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) 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; if (!source_expr) return NULL;
Expr *expr = expr_shallow_copy(source_expr); Expr *expr = expr_shallow_copy(source_expr);
switch (source_expr->expr_kind) switch (source_expr->expr_kind)
{ {
case EXPR_TYPEOF:
MACRO_COPY_EXPR(expr->typeof_expr);
return expr;
case EXPR_COMPOUND_LITERAL: case EXPR_COMPOUND_LITERAL:
EXPR_COPY(expr->expr_compound_literal.initializer); MACRO_COPY_EXPR(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_TYPE(expr->expr_compound_literal.type_info);
return expr; return expr;
case EXPR_DESIGNATED_INITIALIZER: case EXPR_DESIGNATED_INITIALIZER:
// Created during semantic analysis // Created during semantic analysis
UNREACHABLE UNREACHABLE
case EXPR_RANGE: case EXPR_RANGE:
EXPR_COPY(expr->range_expr.left); MACRO_COPY_EXPR(expr->range_expr.left);
EXPR_COPY(expr->range_expr.right); MACRO_COPY_EXPR(expr->range_expr.right);
return expr; return expr;
case EXPR_EXPR_BLOCK: 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; return expr;
case EXPR_POISONED: case EXPR_POISONED:
return source_expr; return source_expr;
case EXPR_TRY: case EXPR_TRY:
EXPR_COPY(expr->try_expr.expr); MACRO_COPY_EXPR(expr->try_expr.expr);
EXPR_COPY(expr->try_expr.else_expr); MACRO_COPY_EXPR(expr->try_expr.else_expr);
return expr; return expr;
case EXPR_CONST: case EXPR_CONST:
return expr; return expr;
case EXPR_BINARY: case EXPR_BINARY:
EXPR_COPY(expr->binary_expr.left); MACRO_COPY_EXPR(expr->binary_expr.left);
EXPR_COPY(expr->binary_expr.right); MACRO_COPY_EXPR(expr->binary_expr.right);
return expr; return expr;
case EXPR_TERNARY: case EXPR_TERNARY:
EXPR_COPY(expr->ternary_expr.cond); MACRO_COPY_EXPR(expr->ternary_expr.cond);
EXPR_COPY(expr->ternary_expr.then_expr); MACRO_COPY_EXPR(expr->ternary_expr.then_expr);
EXPR_COPY(expr->ternary_expr.else_expr); MACRO_COPY_EXPR(expr->ternary_expr.else_expr);
return expr; return expr;
case EXPR_UNARY: case EXPR_UNARY:
EXPR_COPY(expr->unary_expr.expr); MACRO_COPY_EXPR(expr->unary_expr.expr);
return expr; return expr;
case EXPR_POST_UNARY: case EXPR_POST_UNARY:
EXPR_COPY(expr->post_expr.expr); MACRO_COPY_EXPR(expr->post_expr.expr);
return expr; return expr;
case EXPR_TYPE: case EXPR_TYPEID:
expr->type_expr.type = type_info_copy_from_macro(context, macro, expr->type_expr.type); MACRO_COPY_TYPE(expr->typeid_expr);
return expr; return expr;
case EXPR_IDENTIFIER: case EXPR_IDENTIFIER:
TODO TODO
break; break;
case EXPR_TYPE_ACCESS: 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; return expr;
case EXPR_CALL: case EXPR_CALL:
EXPR_COPY(expr->call_expr.function); MACRO_COPY_EXPR(expr->call_expr.function);
expr->call_expr.arguments = expr_copy_expr_list_from_macro(context, macro, expr->call_expr.arguments); MACRO_COPY_EXPR_LIST(expr->call_expr.arguments);
return expr; return expr;
case EXPR_SIZEOF:
TODO
break;
case EXPR_SUBSCRIPT: case EXPR_SUBSCRIPT:
EXPR_COPY(expr->subscript_expr.expr); MACRO_COPY_EXPR(expr->subscript_expr.expr);
EXPR_COPY(expr->subscript_expr.index); MACRO_COPY_EXPR(expr->subscript_expr.index);
return expr; return expr;
case EXPR_GROUP: case EXPR_GROUP:
EXPR_COPY(expr->group_expr->group_expr); MACRO_COPY_EXPR(expr->group_expr->group_expr);
return expr; return expr;
case EXPR_ACCESS: case EXPR_ACCESS:
EXPR_COPY(expr->access_expr.parent); MACRO_COPY_EXPR(expr->access_expr.parent);
return expr; return expr;
case EXPR_INITIALIZER_LIST: 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; return expr;
case EXPR_EXPRESSION_LIST: 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; return expr;
case EXPR_CAST: case EXPR_CAST:
EXPR_COPY(expr->cast_expr.expr); MACRO_COPY_EXPR(expr->cast_expr.expr);
expr->cast_expr.type_info = type_info_copy_from_macro(context, macro, expr->cast_expr.type_info); MACRO_COPY_TYPE(expr->cast_expr.type_info);
return expr; return expr;
case EXPR_SCOPED_EXPR: case EXPR_SCOPED_EXPR:
EXPR_COPY(expr->expr_scope.expr); MACRO_COPY_EXPR(expr->expr_scope.expr);
return expr; return expr;
case EXPR_MACRO_EXPR: case EXPR_MACRO_EXPR:
EXPR_COPY(expr->macro_expr); MACRO_COPY_EXPR(expr->macro_expr);
return expr; return expr;
} }
#undef EXPR_COPY
UNREACHABLE 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 **result = NULL;
TypeInfo **list = *to_convert; VECEACH(to_copy, i)
VECEACH(list, 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) 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); Ast *ast = ast_shallow_copy(source);
switch (source->ast_kind) switch (source->ast_kind)
{ {
@@ -2400,87 +2408,87 @@ static Ast *ast_copy_from_macro(Context *context, Expr *macro, Ast *source)
case AST_BREAK_STMT: case AST_BREAK_STMT:
return ast; return ast;
case AST_CASE_STMT: case AST_CASE_STMT:
AST_COPY(ast->case_stmt.body); MACRO_COPY_AST(ast->case_stmt.body);
EXPR_COPY(ast->case_stmt.expr); MACRO_COPY_EXPR(ast->case_stmt.expr);
return ast; return ast;
break; break;
case AST_CATCH_STMT: case AST_CATCH_STMT:
AST_COPY(ast->catch_stmt.body); MACRO_COPY_AST(ast->catch_stmt.body);
return ast; return ast;
case AST_COMPOUND_STMT: 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; return ast;
case AST_CONTINUE_STMT: case AST_CONTINUE_STMT:
return ast; return ast;
case AST_CT_IF_STMT: case AST_CT_IF_STMT:
EXPR_COPY(ast->ct_if_stmt.expr); MACRO_COPY_EXPR(ast->ct_if_stmt.expr);
AST_COPY(ast->ct_if_stmt.elif); MACRO_COPY_AST(ast->ct_if_stmt.elif);
AST_COPY(ast->ct_if_stmt.then); MACRO_COPY_AST(ast->ct_if_stmt.then);
return ast; return ast;
case AST_CT_ELIF_STMT: case AST_CT_ELIF_STMT:
EXPR_COPY(ast->ct_elif_stmt.expr); MACRO_COPY_EXPR(ast->ct_elif_stmt.expr);
AST_COPY(ast->ct_elif_stmt.then); MACRO_COPY_AST(ast->ct_elif_stmt.then);
AST_COPY(ast->ct_elif_stmt.elif); MACRO_COPY_AST(ast->ct_elif_stmt.elif);
return ast; return ast;
case AST_CT_ELSE_STMT: case AST_CT_ELSE_STMT:
AST_COPY(ast->ct_else_stmt); MACRO_COPY_AST(ast->ct_else_stmt);
return ast; return ast;
case AST_CT_FOR_STMT: case AST_CT_FOR_STMT:
AST_COPY(ast->ct_for_stmt.body); MACRO_COPY_AST(ast->ct_for_stmt.body);
EXPR_COPY(ast->ct_for_stmt.expr); MACRO_COPY_EXPR(ast->ct_for_stmt.expr);
return ast; return ast;
case AST_CT_SWITCH_STMT: case AST_CT_SWITCH_STMT:
EXPR_COPY(ast->ct_switch_stmt.cond); MACRO_COPY_EXPR(ast->ct_switch_stmt.cond);
ast_copy_list_from_macro(context, macro, &ast->ct_switch_stmt.body); MACRO_COPY_AST_LIST(ast->ct_switch_stmt.body);
return ast; return ast;
case AST_CT_DEFAULT_STMT: case AST_CT_DEFAULT_STMT:
AST_COPY(ast->ct_default_stmt); MACRO_COPY_AST(ast->ct_default_stmt);
return ast; return ast;
case AST_CT_CASE_STMT: case AST_CT_CASE_STMT:
AST_COPY(ast->ct_case_stmt.body); MACRO_COPY_AST(ast->ct_case_stmt.body);
type_info_copy_list_from_macro(context, macro, &ast->ct_case_stmt.types); MACRO_COPY_TYPE_LIST(ast->ct_case_stmt.types);
return ast; return ast;
case AST_DECLARE_STMT: case AST_DECLARE_STMT:
TODO TODO
return ast; return ast;
case AST_DEFAULT_STMT: case AST_DEFAULT_STMT:
AST_COPY(ast->case_stmt.body); MACRO_COPY_AST(ast->case_stmt.body);
return ast; return ast;
case AST_DEFER_STMT: case AST_DEFER_STMT:
assert(!ast->defer_stmt.prev_defer); assert(!ast->defer_stmt.prev_defer);
AST_COPY(ast->defer_stmt.body); MACRO_COPY_AST(ast->defer_stmt.body);
return ast; return ast;
case AST_DO_STMT: case AST_DO_STMT:
AST_COPY(ast->do_stmt.body); MACRO_COPY_AST(ast->do_stmt.body);
EXPR_COPY(ast->do_stmt.expr); MACRO_COPY_EXPR(ast->do_stmt.expr);
return ast; return ast;
case AST_EXPR_STMT: case AST_EXPR_STMT:
EXPR_COPY(ast->expr_stmt); MACRO_COPY_EXPR(ast->expr_stmt);
return ast; return ast;
case AST_FOR_STMT: case AST_FOR_STMT:
EXPR_COPY(ast->for_stmt.cond); MACRO_COPY_EXPR(ast->for_stmt.cond);
EXPR_COPY(ast->for_stmt.incr); MACRO_COPY_EXPR(ast->for_stmt.incr);
AST_COPY(ast->for_stmt.body); MACRO_COPY_AST(ast->for_stmt.body);
AST_COPY(ast->for_stmt.init); MACRO_COPY_AST(ast->for_stmt.init);
return ast; return ast;
case AST_GENERIC_CASE_STMT: 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 = ... // ast->generic_case_stmt.types = ...
TODO TODO
return ast; return ast;
case AST_GENERIC_DEFAULT_STMT: case AST_GENERIC_DEFAULT_STMT:
AST_COPY(ast->generic_default_stmt); MACRO_COPY_AST(ast->generic_default_stmt);
return ast; return ast;
case AST_GOTO_STMT: 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 fixup name, which needs to be macro local.
TODO TODO
return ast; return ast;
case AST_IF_STMT: case AST_IF_STMT:
AST_COPY(ast->if_stmt.cond); MACRO_COPY_AST(ast->if_stmt.cond);
AST_COPY(ast->if_stmt.decl); MACRO_COPY_AST(ast->if_stmt.decl);
AST_COPY(ast->if_stmt.else_body); MACRO_COPY_AST(ast->if_stmt.else_body);
AST_COPY(ast->if_stmt.then_body); MACRO_COPY_AST(ast->if_stmt.then_body);
return ast; return ast;
case AST_LABEL: case AST_LABEL:
assert(!ast->label_stmt.defer); 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: case AST_NOP_STMT:
return ast; return ast;
case AST_RETURN_STMT: case AST_RETURN_STMT:
EXPR_COPY(ast->return_stmt.expr); MACRO_COPY_EXPR(ast->return_stmt.expr);
// TODO handle conversions? // TODO handle conversions?
TODO TODO
return ast; return ast;
case AST_DECL_EXPR_LIST: 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; return ast;
case AST_SWITCH_STMT: case AST_SWITCH_STMT:
AST_COPY(ast->switch_stmt.decl); MACRO_COPY_AST(ast->switch_stmt.decl);
AST_COPY(ast->switch_stmt.cond); MACRO_COPY_AST(ast->switch_stmt.cond);
ast_copy_list_from_macro(context, macro, &ast->switch_stmt.cases); MACRO_COPY_AST_LIST(ast->switch_stmt.cases);
return ast; return ast;
case AST_THROW_STMT: case AST_THROW_STMT:
EXPR_COPY(ast->throw_stmt.throw_value); MACRO_COPY_EXPR(ast->throw_stmt.throw_value);
return ast; return ast;
case AST_TRY_STMT: case AST_TRY_STMT:
AST_COPY(ast->try_stmt); MACRO_COPY_AST(ast->try_stmt);
return ast; return ast;
case AST_NEXT_STMT: case AST_NEXT_STMT:
TODO TODO
@@ -2516,17 +2524,15 @@ static Ast *ast_copy_from_macro(Context *context, Expr *macro, Ast *source)
TODO TODO
return ast; return ast;
case AST_WHILE_STMT: case AST_WHILE_STMT:
AST_COPY(ast->while_stmt.cond); MACRO_COPY_AST(ast->while_stmt.cond);
AST_COPY(ast->while_stmt.decl); MACRO_COPY_AST(ast->while_stmt.decl);
AST_COPY(ast->while_stmt.body); MACRO_COPY_AST(ast->while_stmt.body);
return ast; return ast;
case AST_SCOPED_STMT: case AST_SCOPED_STMT:
AST_COPY(ast->scoped_stmt.stmt); MACRO_COPY_AST(ast->scoped_stmt.stmt);
return ast; return ast;
} }
UNREACHABLE; UNREACHABLE;
#undef EXPR_COPY
#undef AST_COPY
} }
static inline bool sema_expr_analyse_macro_call(Context *context, Type *to, Expr *macro, Expr *inner) 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) 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); return expr_poison(expr);
} }
expr->type = type_get_meta(expr->type_expr.type->type); expr->type = type_typeid;
return true; return true;
} }
@@ -2750,6 +2756,16 @@ static inline bool sema_expr_analyse_compound_literal(Context *context, Type *to
return true; 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) static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *expr)
{ {
switch (expr->expr_kind) switch (expr->expr_kind)
@@ -2761,6 +2777,8 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *
UNREACHABLE UNREACHABLE
case EXPR_SCOPED_EXPR: case EXPR_SCOPED_EXPR:
UNREACHABLE UNREACHABLE
case EXPR_TYPEOF:
return sema_expr_analyse_typeof(context, expr);
case EXPR_COMPOUND_LITERAL: case EXPR_COMPOUND_LITERAL:
return sema_expr_analyse_compound_literal(context, to, expr); return sema_expr_analyse_compound_literal(context, to, expr);
case EXPR_EXPR_BLOCK: 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); return sema_expr_analyse_unary(context, to, expr);
case EXPR_POST_UNARY: case EXPR_POST_UNARY:
return sema_expr_analyse_post_unary(context, to, expr); return sema_expr_analyse_post_unary(context, to, expr);
case EXPR_TYPE: case EXPR_TYPEID:
return sema_expr_analyse_type(context, to, expr); return sema_expr_analyse_type(context, to, expr);
case EXPR_IDENTIFIER: case EXPR_IDENTIFIER:
return sema_expr_analyse_identifier(context, to, expr); 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); return sema_expr_analyse_type_access(context, to, expr);
case EXPR_CALL: case EXPR_CALL:
return sema_expr_analyse_call(context, to, expr); return sema_expr_analyse_call(context, to, expr);
case EXPR_SIZEOF:
return sema_expr_analyse_sizeof(context, to, expr);
case EXPR_SUBSCRIPT: case EXPR_SUBSCRIPT:
return sema_expr_analyse_subscript(context, to, expr); return sema_expr_analyse_subscript(context, to, expr);
case EXPR_GROUP: case EXPR_GROUP:

View File

@@ -140,10 +140,12 @@ const char *token_type_to_string(TokenType type)
// Identifiers // Identifiers
case TOKEN_IDENT: case TOKEN_IDENT:
return "IDENT"; return "IDENT";
case TOKEN_HASH_IDENT:
return "HASH_IDENT";
case TOKEN_CT_IDENT: case TOKEN_CT_IDENT:
return "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: case TOKEN_CONST_IDENT:
return "CONST_IDENT"; return "CONST_IDENT";
case TOKEN_TYPE_IDENT: case TOKEN_TYPE_IDENT:
@@ -240,8 +242,10 @@ const char *token_type_to_string(TokenType type)
return "true"; return "true";
case TOKEN_TRY: case TOKEN_TRY:
return "try"; return "try";
case TOKEN_TYPE: case TOKEN_TYPEID:
return "type"; return "typeid";
case TOKEN_TYPEOF:
return "typeof";
case TOKEN_TYPEDEF: case TOKEN_TYPEDEF:
return "typedef"; return "typedef";
case TOKEN_UNION: case TOKEN_UNION:

View File

@@ -43,11 +43,9 @@ Type *type_c_uint = &t_cui;
Type *type_c_ulong = &t_cul; Type *type_c_ulong = &t_cul;
Type *type_c_ulonglong = &t_cull; Type *type_c_ulonglong = &t_cull;
#define PTR_OFFSET 0
#define META_OFFSET 0 #define VAR_ARRAY_OFFSET 1
#define PTR_OFFSET 1 #define ARRAY_OFFSET 2
#define VAR_ARRAY_OFFSET 2
#define ARRAY_OFFSET 3
Type *type_signed_int_by_bitsize(unsigned bytesize) Type *type_signed_int_by_bitsize(unsigned bytesize)
{ {
@@ -196,8 +194,6 @@ size_t type_size(Type *canonical)
case TYPE_POISONED: case TYPE_POISONED:
case TYPE_TYPEDEF: case TYPE_TYPEDEF:
UNREACHABLE; UNREACHABLE;
case TYPE_META_TYPE:
return 0;
case TYPE_ENUM: case TYPE_ENUM:
return canonical->decl->enums.type_info->type->canonical->builtin.bytesize; return canonical->decl->enums.type_info->type->canonical->builtin.bytesize;
case TYPE_ERROR: case TYPE_ERROR:
@@ -208,6 +204,7 @@ size_t type_size(Type *canonical)
case TYPE_VOID: case TYPE_VOID:
return 1; return 1;
case TYPE_BOOL: case TYPE_BOOL:
case TYPE_META_TYPE:
case ALL_INTS: case ALL_INTS:
case ALL_FLOATS: case ALL_FLOATS:
return canonical->builtin.bytesize; return canonical->builtin.bytesize;
@@ -235,8 +232,6 @@ unsigned int type_abi_alignment(Type *canonical)
case TYPE_TYPEDEF: case TYPE_TYPEDEF:
case TYPE_VOID: case TYPE_VOID:
UNREACHABLE; UNREACHABLE;
case TYPE_META_TYPE:
return 0;
case TYPE_ENUM: case TYPE_ENUM:
return canonical->decl->enums.type_info->type->canonical->builtin.abi_alignment; return canonical->decl->enums.type_info->type->canonical->builtin.abi_alignment;
case TYPE_ERROR: case TYPE_ERROR:
@@ -244,6 +239,7 @@ unsigned int type_abi_alignment(Type *canonical)
case TYPE_STRUCT: case TYPE_STRUCT:
case TYPE_UNION: case TYPE_UNION:
return canonical->decl->strukt.abi_alignment; return canonical->decl->strukt.abi_alignment;
case TYPE_META_TYPE:
case TYPE_BOOL: case TYPE_BOOL:
case ALL_INTS: case ALL_INTS:
case ALL_FLOATS: case ALL_FLOATS:
@@ -298,31 +294,6 @@ static Type *type_generate_ptr(Type *ptr_type, bool canonical)
return ptr; 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) 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); 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) Type *type_get_indexed_type(Type *type)
{ {
switch (type->type_kind) switch (type->type_kind)
@@ -472,6 +438,7 @@ type_create(#_name, &_shortname, _type, _bits, target->align_ ## _align, target-
#undef DEF_TYPE #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); type_create("void*", &t_voidstar, TYPE_POINTER, target->width_pointer, target->align_pref_pointer, target->align_pointer);
create_type_cache(type_void); create_type_cache(type_void);
type_void->type_cache[0] = &t_voidstar; 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)); type_create_alias("c_int", &t_ci, type_signed_int_by_bitsize(target->width_c_int));
// TODO fix error size // TODO fix error size
type_create_alias("error", &t_err, type_signed_int_by_bitsize(target->width_c_int)); 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_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)); type_create_alias("c_longlong", &t_cll, type_signed_int_by_bitsize(target->width_c_long_long));