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);
%}
%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

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;
}
/*
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));

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_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");

View File

@@ -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;

View File

@@ -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

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
// 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);
}

View File

@@ -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];

View File

@@ -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:

View File

@@ -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

View File

@@ -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;

View File

@@ -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:

View File

@@ -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:

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.");
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 },

View File

@@ -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:

View File

@@ -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);
}

View File

@@ -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, ...);

View File

@@ -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:

View File

@@ -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:

View File

@@ -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));