libpulsar
A modular compiler for the pulsar programming language
Loading...
Searching...
No Matches
type.c
Go to the documentation of this file.
1// Copyright (C) 2023 Ethan Uppal. All rights reserved.
2
3#include <string.h> // strcmp
4#include "type.h"
5#include "util/abort.h" // CHECK, ps_assert
6#include "util/arena.h" // astalloc
7
18
20 return type >= PS_TYPE_U8 && type <= PS_TYPE_B;
21}
22
23struct ps_type* ps_type_prim_new(enum ps_type_type prim_type) {
24 ps_assert(ps_type_is_prim(prim_type), "precondition");
25
26 struct ps_type* type = astalloc(sizeof(*type));
27 if (!type) {
29 return NULL;
30 }
31
32 type->type = prim_type;
33
34 return type;
35}
36
37struct ps_type* ps_type_struct_new(struct ps_token* name) {
38 struct ps_type* type = astalloc(sizeof(*type));
39
40 type->type = PS_TYPE_STRUCT;
41 type->value.struct_.name = name;
42 type->value.struct_.fields = ps_type_field_arr_new(); // leaks
43
44 return type;
45}
46
47void ps_type_struct_add(struct ps_type* type, struct ps_type_field field) {
48 ps_assert(type->type == PS_TYPE_STRUCT, "precondition");
49 ps_push(&type->value.struct_.fields, field);
50}
51
52struct ps_type* ps_type_enum_new(struct ps_token* name) {
53 struct ps_type* type = astalloc(sizeof(*type));
54
55 type->type = PS_TYPE_ENUM;
56 type->value.enum_.name = name;
57 type->value.enum_.variants = ps_type_variant_arr_new(); // leaks
58
59 return type;
60}
61
62void ps_type_enum_add(struct ps_type* type, struct ps_type_variant variant) {
63 ps_assert(type->type == PS_TYPE_ENUM, "precondition");
64 ps_push(&type->value.enum_.variants, variant);
65}
66
68 struct ps_type* type = astalloc(sizeof(*type));
69
70 type->type = PS_TYPE_UNRESOLVED;
71 type->value.unresolved = name;
72
73 return type;
74}
75
76struct ps_type* ps_type_from_name(struct ps_token* name) {
77 ps_assert(name->type == PS_TOKEN_ID, "type name should be an identifer");
78 for (usize i = 0; i < lengthof(prim_type_names); i++) {
79 if (strcmp(prim_type_names[i], name->start) == 0) {
80 return ps_type_prim_new((enum ps_type_type)i);
81 }
82 }
83 return ps_type_unresolved_new(name);
84}
85
86struct ps_type* ps_type_from_tuple(struct ps_type_tuple* tuple) {
87 struct ps_type* type = astalloc(sizeof(*type));
88
89 type->type = PS_TYPE_TUPLE;
90 type->value.tuple = tuple;
91
92 return type;
93}
94
96 switch (self->type) {
97 case PS_TYPE_U8: {
98 fputs(_STRING(PS_PRIM_TYPE_U8), stdout);
99 break;
100 }
101 case PS_TYPE_I8: {
102 fputs(_STRING(PS_PRIM_TYPE_I8), stdout);
103 break;
104 }
105 case PS_TYPE_U16: {
106 fputs(_STRING(PS_PRIM_TYPE_U16), stdout);
107 break;
108 }
109 case PS_TYPE_I16: {
110 fputs(_STRING(PS_PRIM_TYPE_I16), stdout);
111 break;
112 }
113 case PS_TYPE_U32: {
114 fputs(_STRING(PS_PRIM_TYPE_U32), stdout);
115 break;
116 }
117 case PS_TYPE_I32: {
118 fputs(_STRING(PS_PRIM_TYPE_I32), stdout);
119 break;
120 }
121 case PS_TYPE_U64: {
122 fputs(_STRING(PS_PRIM_TYPE_U64), stdout);
123 break;
124 }
125 case PS_TYPE_I64: {
126 fputs(_STRING(PS_PRIM_TYPE_I64), stdout);
127 break;
128 }
129 case PS_TYPE_F32: {
130 fputs(_STRING(PS_PRIM_TYPE_F32), stdout);
131 break;
132 }
133 case PS_TYPE_F64: {
134 fputs(_STRING(PS_PRIM_TYPE_F64), stdout);
135 break;
136 }
137 case PS_TYPE_B: {
138 fputs(_STRING(PS_PRIM_TYPE_B), stdout);
139 break;
140 }
141 case PS_TYPE_TUPLE: {
142 ps_type_tuple_print(self->value.tuple, 0);
143 break;
144 }
145 case PS_TYPE_STRUCT: {
146 ps_type_struct_print(&self->value.struct_, 0, 0);
147 break;
148 }
149 case PS_TYPE_ENUM: {
150 ps_type_enum_print(&self->value.enum_, 0, 0);
151 break;
152 }
153 case PS_TYPE_UNRESOLVED: {
154 printf("%s", self->value.unresolved->start);
155 break;
156 }
157 default: {
158 ps_abort("unknown type encountered");
159 break;
160 }
161 }
162})
163
164PS_PRINT_IMPL(ps_type_tuple, {
165 printf("(");
166 for (usize i = 0; i < self->length; i++) {
167 ps_type_print(self->contents[i], 0);
168 if (i < self->length - 1) {
169 printf(", ");
170 }
171 }
172 printf(")");
173})
174
176 printf("%s", self->name);
177 ps_type_tuple_print(self->args, 0);
178})
179
182 printf("struct %.*s {\n", (int)self->name->length, self->name->start);
183 for (usize i = 0; i < self->fields->length; i++) {
184 ps_type_field_print(&$arr(self->fields)[i], 0, ps_next_indent());
185 printf("\n");
186 }
188 printf("}");
189})
190
193 printf("enum %.*s {\n", (int)self->name->length, self->name->start);
194 for (usize i = 0; i < self->variants->length; i++) {
195 ps_type_variant_print(&$arr(self->variants)[i], 0);
196 printf("\n");
197 }
199 printf("}");
200})
201
204 printf("%s: ", self->name);
205 ps_type_print(self->type, 0);
206})
207
208PS_PRINT_IMPL(ps_type_field_arr, {
209 printf("(");
210 for (usize i = 0; i < self->length; i++) {
211 if (i) printf(", ");
212 ps_type_field_print(&self->contents[i], 0, 0);
213 }
214 printf(")");
215})
Defines assertion and abortion functionality.
#define ps_abort(msg)
Aborts the program with the given message.
Definition abort.h:47
#define PS_NO_MEMORY()
Aborts the program due to exhaustion of virtual memory.
Definition abort.h:65
#define ps_assert(cond, msg)
Asserts the given condition cond, aborting via ps_abort with the given msg otherwise.
Definition abort.h:53
Defines an arena allocator for the compiler.
#define astalloc(n)
Definition arena.h:51
#define STR
Definition def.h:40
#define lengthof(array)
Definition def.h:55
#define _STRING(x)
Definition def.h:74
#define usize
Definition def.h:50
#define ps_push(__arrptr, __new_elem)
Definition dynarr.h:46
static void usize length
Definition lexer.h:71
#define PS_IPRINT_IMPL(T,...)
Definition print.h:20
#define ps_print_indent()
Definition print.h:27
#define ps_next_indent()
Definition print.h:28
#define PS_PRINT_IMPL(T,...)
Definition print.h:10
Represents a token.
Definition token.h:34
enum ps_token_type type
Definition token.h:36
STR start
Definition token.h:37
A pair (string, type).
Definition type.h:15
A pair (string, types).
Definition type.h:21
Definition type.h:66
struct ps_type_tuple * tuple
Definition type.h:69
enum ps_type_type type
Definition type.h:67
struct ps_type * ps_type_struct_new(struct ps_token *name)
Constructs a new empty struct type with the name name.
Definition type.c:37
struct ps_type * ps_type_from_name(struct ps_token *name)
Returns the type associated with the given name (e.g.
Definition type.c:76
struct ps_type * ps_type_enum_new(struct ps_token *name)
Constructs a new empty enum type with the name name.
Definition type.c:52
bool ps_type_is_prim(enum ps_type_type type)
Returns whether type represents a primitive type.
Definition type.c:19
struct ps_type * ps_type_from_tuple(struct ps_type_tuple *tuple)
Constructs and returns a type for the given tuple type tuple.
Definition type.c:86
STR prim_type_names[]
For each type PS_TYPE_U8 to PS_TYPE_B, this array indexes by prim_type_names[PS_TYPE_U8] == _STRING(P...
Definition type.c:12
void ps_type_struct_add(struct ps_type *type, struct ps_type_field field)
Adds the given field field to the struct type type.
Definition type.c:47
struct ps_type * ps_type_prim_new(enum ps_type_type prim_type)
Constructs a new primitive type specified by prim_type.
Definition type.c:23
struct ps_type * ps_type_unresolved_new(struct ps_token *name)
Constructs a new unresolved type corresponding to the given name.
Definition type.c:67
void ps_type_enum_add(struct ps_type *type, struct ps_type_variant variant)
Adds the given variant variant to the struct type type.
Definition type.c:62
#define ps_type_field_arr_new()
Definition type.h:30
ps_type_type
The type of a type :)
Definition type.h:60
#define ps_type_variant_arr_new()
Definition type.h:37
#define PS_PRIM_TYPE_F32
Definition type_prim.h:11
#define PS_PRIM_TYPE_I16
Definition type_prim.h:6
#define PS_PRIM_TYPE_B
Definition type_prim.h:13
#define PS_PRIM_TYPE_F64
Definition type_prim.h:12
#define PS_PRIM_TYPE_I64
Definition type_prim.h:10
#define PS_PRIM_TYPE_U16
Definition type_prim.h:5
#define PS_PRIM_TYPE_U64
Definition type_prim.h:9
#define PS_PRIM_TYPE_I32
Definition type_prim.h:8
#define PS_PRIM_TYPE_U32
Definition type_prim.h:7
#define PS_PRIM_TYPE_I8
Definition type_prim.h:4
#define PS_PRIM_TYPE_U8
Definition type_prim.h:3