- commit
- 407d53b
- parent
- aad8fd0
- author
- xplshn
- date
- 2025-09-14 08:47:52 +0000 UTC
make pointers go-like Signed-off-by: xplshn <[email protected]>
10 files changed,
+170,
-154
+7,
-7
1@@ -60,7 +60,12 @@ func main() {
2 cfg.SetWarning(config.WarnPedantic, true)
3 }
4
5- // Apply warning flags
6+ // Apply language standard first
7+ if err := cfg.ApplyStd(std); err != nil {
8+ util.Error(token.Token{}, err.Error())
9+ }
10+
11+ // Apply warning flags (override standard settings)
12 for i, entry := range warningFlags {
13 if entry.Enabled != nil && *entry.Enabled {
14 cfg.SetWarning(config.Warning(i), true)
15@@ -70,7 +75,7 @@ func main() {
16 }
17 }
18
19- // Apply feature flags
20+ // Apply feature flags (override standard settings)
21 for i, entry := range featureFlags {
22 if entry.Enabled != nil && *entry.Enabled {
23 cfg.SetFeature(config.Feature(i), true)
24@@ -80,11 +85,6 @@ func main() {
25 }
26 }
27
28- // Apply language standard
29- if err := cfg.ApplyStd(std); err != nil {
30- util.Error(token.Token{}, err.Error())
31- }
32-
33 // Set target architecture
34 cfg.SetTarget(runtime.GOOS, runtime.GOARCH, target)
35
+5,
-5
1@@ -36,11 +36,11 @@ int main() {
2 now := time(0);
3 tptr := localtime(&now);
4
5- byte_ptr := (byte*)tptr;
6- year := *((int*)(byte_ptr + 20)) + 1900;
7- month := *((int*)(byte_ptr + 16)); // 0 = Jan
8- today := *((int*)(byte_ptr + 12));
9- wday := *((int*)(byte_ptr + 24));
10+ byte_ptr := (*byte)tptr;
11+ year := *((*int)(byte_ptr + 20)) + 1900;
12+ month := *((*int)(byte_ptr + 16)); // 0 = Jan
13+ today := *((*int)(byte_ptr + 12));
14+ wday := *((*int)(byte_ptr + 24));
15
16 days := days_in_month(month, year);
17
+7,
-7
1@@ -10,14 +10,14 @@ extrn putchar, getchar, printf, scanf, strlen, strcpy, strcmp, malloc;
2 int TABLE_SIZE = 101;
3
4 type struct Entry {
5- key byte*;
6- value byte*;
7- next Entry*;
8+ key *byte;
9+ value *byte;
10+ next *Entry;
11 };
12
13-Entry* table[TABLE_SIZE];
14+*Entry table[TABLE_SIZE];
15
16-int hash(key byte*) {
17+int hash(key *byte) {
18 result := 0;
19 i := 0;
20 while (key[i] != 0) {
21@@ -27,7 +27,7 @@ int hash(key byte*) {
22 return ((result % TABLE_SIZE + TABLE_SIZE) % TABLE_SIZE);
23 }
24
25-void set(key, value byte*) {
26+void set(key, value *byte) {
27 index := hash(key);
28 entry := table[index];
29
30@@ -53,7 +53,7 @@ void set(key, value byte*) {
31 table[index] = new_entry;
32 }
33
34-byte* get(key byte*) {
35+*byte get(key *byte) {
36 index := hash(key);
37 entry := table[index];
38
+1,
-1
1@@ -7,7 +7,7 @@ byte word_buf[50];
2 int line_len;
3 int word_len;
4
5-void print_string(s byte*, len int) {
6+void print_string(s *byte, len int) {
7 auto i;
8 i = 0;
9 while (i < len) {
+3,
-1
1@@ -260,7 +260,9 @@ func (c *Config) ApplyStd(stdName string) error {
2 {FeatExtrn, !isPedantic, true}, {FeatAsm, !isPedantic, true},
3 {FeatTyped, false, true}, {FeatShortDecl, false, true},
4 {FeatBxDeclarations, false, true}, {FeatStrictDecl, false, isPedantic},
5- {FeatFloat, false, true},
6+ {FeatContinue, false, true}, {FeatNoDirectives, false, false},
7+ {FeatFloat, false, true}, {FeatStrictTypes, false, false},
8+ {FeatPromTypes, false, false},
9 }
10
11 switch stdName {
+136,
-122
1@@ -176,7 +176,7 @@ func (p *Parser) parseTopLevel() *ast.Node {
2 stmt = p.parseUntypedGlobalDefinition(identTok)
3 }
4 default:
5- if p.isTypedPass && (p.isBuiltinType(p.current) || p.check(token.Const)) {
6+ if p.isTypedPass && (p.isBuiltinType(p.current) || p.check(token.Const) || p.isPointerTypeAhead()) {
7 stmt = p.parseTypedVarOrFuncDecl(true)
8 } else {
9 stmt = p.parseExpr()
10@@ -242,7 +242,7 @@ func (p *Parser) isBuiltinType(tok token.Token) bool {
11 return tok.Type >= token.Void && tok.Type <= token.Any
12 }
13
14-// isPointerCastAhead checks if the current position looks like a pointer cast: (type*)
15+// isPointerCastAhead checks if the current position looks like a pointer cast: (*type)
16 // This allows complex pointer casts while disallowing simple scalar C-style casts
17 func (p *Parser) isPointerCastAhead() bool {
18 if !p.isTypedPass { return false }
19@@ -252,29 +252,43 @@ func (p *Parser) isPointerCastAhead() bool {
20
21 if p.match(token.Const) {}
22
23- if p.isBuiltinType(p.current) {
24- p.advance()
25- } else if p.check(token.Ident) && p.isTypeName(p.current.Value) {
26- p.advance()
27- } else {
28- return false
29- }
30-
31+ // Check for Go-style pointer syntax: *type
32 hasPointer := false
33 if p.match(token.Star) {
34 hasPointer = true
35- for p.match(token.Star) {}
36+ for p.match(token.Star) {} // Allow multiple stars for pointer-to-pointer
37 }
38
39- if p.match(token.LBracket) {
40+ if p.isBuiltinType(p.current) {
41+ p.advance()
42+ } else if p.check(token.Ident) && p.isTypeName(p.current.Value) {
43+ p.advance()
44+ } else if p.match(token.LBracket) {
45 hasPointer = true
46 for !p.check(token.RBracket) && !p.check(token.EOF) { p.advance() }
47 if p.check(token.RBracket) { p.advance() }
48+ } else {
49+ return false
50 }
51
52 return hasPointer && p.check(token.RParen)
53 }
54
55+func (p *Parser) isPointerTypeAhead() bool {
56+ if !p.check(token.Star) { return false }
57+
58+ originalPos, originalCurrent := p.pos, p.current
59+ defer func() { p.pos, p.current = originalPos, originalCurrent }()
60+
61+ // Skip all consecutive * tokens
62+ for p.check(token.Star) {
63+ p.advance()
64+ }
65+
66+ // Check if what follows the * is actually a type name
67+ return p.isBuiltinType(p.current) || (p.check(token.Ident) && p.isTypeName(p.current.Value))
68+}
69+
70 func (p *Parser) parseStmt() *ast.Node {
71 tok := p.current
72
73@@ -298,7 +312,7 @@ func (p *Parser) parseStmt() *ast.Node {
74 return ast.NewLabel(tok, labelName, p.parseStmt())
75 }
76
77- if p.isTypedPass && (p.isBuiltinType(p.current) || (p.isTypeName(p.current.Value) && p.peek().Type != token.Define) || p.check(token.Const)) {
78+ if p.isTypedPass && (p.isBuiltinType(p.current) || (p.isTypeName(p.current.Value) && p.peek().Type != token.Define) || p.check(token.Const) || p.isPointerTypeAhead()) {
79 return p.parseTypedVarOrFuncDecl(false)
80 }
81
82@@ -882,85 +896,85 @@ func (p *Parser) parseTypedVarDeclBody(startTok token.Token, declType *ast.BxTyp
83 }
84
85 func (p *Parser) parseType() *ast.BxType {
86- if !p.isTypedPass {
87- return nil
88- }
89-
90- isConst := p.match(token.Const)
91- var baseType *ast.BxType
92-
93- if p.match(token.LBracket) {
94- p.expect(token.RBracket, "Expected ']' to complete array type specifier")
95- elemType := p.parseType()
96- baseType = &ast.BxType{Kind: ast.TYPE_ARRAY, Base: elemType}
97- } else {
98- tok := p.current
99- if p.match(token.Struct) {
100- if p.check(token.Ident) && p.peek().Type != token.LBrace {
101- tagName := p.current.Value
102- p.advance()
103- baseType = &ast.BxType{Kind: ast.TYPE_STRUCT, Name: tagName, StructTag: tagName}
104- } else {
105- baseType = p.parseStructDef()
106- }
107- } else if p.match(token.Enum) {
108- if p.check(token.Ident) {
109- tagName := p.current.Value
110- p.advance()
111- baseType = &ast.BxType{Kind: ast.TYPE_ENUM, Name: tagName}
112- } else {
113- util.Error(tok, "Anonymous enums are not supported as types")
114- baseType = ast.TypeUntyped
115- }
116- } else if p.isBuiltinType(tok) {
117- p.advance()
118- var typeName string
119- for keyword, t := range token.KeywordMap {
120- if t == p.previous.Type {
121- typeName = keyword
122- break
123- }
124- }
125-
126- if p.previous.Type == token.Void {
127- baseType = ast.TypeVoid
128- } else if p.previous.Type == token.StringKeyword {
129- baseType = ast.TypeString
130- } else if p.previous.Type >= token.Float && p.previous.Type <= token.Float64 {
131- baseType = &ast.BxType{Kind: ast.TYPE_FLOAT, Name: typeName}
132- } else {
133- if typeName == "" {
134- util.Error(tok, "Internal parser error: could not find string for builtin type %v", tok.Type)
135- return ast.TypeUntyped
136- }
137- baseType = &ast.BxType{Kind: ast.TYPE_PRIMITIVE, Name: typeName}
138- }
139- } else if p.check(token.Ident) {
140- typeName := p.current.Value
141- if !p.isTypeName(typeName) {
142- util.Error(p.current, "Unknown type name '%s'", typeName)
143- p.advance()
144- return ast.TypeUntyped
145- }
146- p.advance()
147- baseType = &ast.BxType{Kind: ast.TYPE_PRIMITIVE, Name: typeName}
148- } else {
149- util.Error(p.current, "Expected a type name, 'struct', 'enum', or '[]'")
150- p.advance()
151- return ast.TypeUntyped
152- }
153- }
154-
155- for p.match(token.Star) {
156- baseType = &ast.BxType{Kind: ast.TYPE_POINTER, Base: baseType}
157- }
158-
159- if isConst {
160- newType := *baseType
161- newType.IsConst = true
162- return &newType
163- }
164- return baseType
165+ if !p.isTypedPass {
166+ return nil
167+ }
168+
169+ isConst := p.match(token.Const)
170+ var baseType *ast.BxType
171+
172+ // Handle Go-style pointer syntax (*int)
173+ if p.match(token.Star) {
174+ elemType := p.parseType()
175+ baseType = &ast.BxType{Kind: ast.TYPE_POINTER, Base: elemType}
176+ } else if p.match(token.LBracket) {
177+ p.expect(token.RBracket, "Expected ']' to complete array type specifier")
178+ elemType := p.parseType()
179+ baseType = &ast.BxType{Kind: ast.TYPE_ARRAY, Base: elemType}
180+ } else {
181+ tok := p.current
182+ if p.match(token.Struct) {
183+ if p.check(token.Ident) && p.peek().Type != token.LBrace {
184+ tagName := p.current.Value
185+ p.advance()
186+ baseType = &ast.BxType{Kind: ast.TYPE_STRUCT, Name: tagName, StructTag: tagName}
187+ } else {
188+ baseType = p.parseStructDef()
189+ }
190+ } else if p.match(token.Enum) {
191+ if p.check(token.Ident) {
192+ tagName := p.current.Value
193+ p.advance()
194+ baseType = &ast.BxType{Kind: ast.TYPE_ENUM, Name: tagName}
195+ } else {
196+ util.Error(tok, "Anonymous enums are not supported as types")
197+ baseType = ast.TypeUntyped
198+ }
199+ } else if p.isBuiltinType(tok) {
200+ p.advance()
201+ var typeName string
202+ for keyword, t := range token.KeywordMap {
203+ if t == p.previous.Type {
204+ typeName = keyword
205+ break
206+ }
207+ }
208+
209+ if p.previous.Type == token.Void {
210+ baseType = ast.TypeVoid
211+ } else if p.previous.Type == token.StringKeyword {
212+ baseType = ast.TypeString
213+ } else if p.previous.Type >= token.Float && p.previous.Type <= token.Float64 {
214+ baseType = &ast.BxType{Kind: ast.TYPE_FLOAT, Name: typeName}
215+ } else {
216+ if typeName == "" {
217+ util.Error(tok, "Internal parser error: could not find string for builtin type %v", tok.Type)
218+ return ast.TypeUntyped
219+ }
220+ baseType = &ast.BxType{Kind: ast.TYPE_PRIMITIVE, Name: typeName}
221+ }
222+ } else if p.check(token.Ident) {
223+ typeName := p.current.Value
224+ if !p.isTypeName(typeName) {
225+ util.Error(p.current, "Unknown type name '%s'", typeName)
226+ p.advance()
227+ return ast.TypeUntyped
228+ }
229+ p.advance()
230+ baseType = &ast.BxType{Kind: ast.TYPE_PRIMITIVE, Name: typeName}
231+ } else {
232+ util.Error(p.current, "Expected a type name, 'struct', 'enum', or '[]'")
233+ p.advance()
234+ return ast.TypeUntyped
235+ }
236+ }
237+
238+ if isConst {
239+ newType := *baseType
240+ newType.IsConst = true
241+ return &newType
242+ }
243+ return baseType
244 }
245
246 func (p *Parser) parseStructDef() *ast.BxType {
247@@ -1129,21 +1143,21 @@ func (p *Parser) parseAssignmentExpr() *ast.Node {
248 // Try to detect multi-assignment pattern: lhs1, lhs2, ... = rhs1, rhs2, ...
249 startPos := p.pos
250 startCurrent := p.current
251-
252+
253 // Parse first expression
254 left := p.parseTernaryExpr()
255-
256+
257 // Check if this could be a multi-assignment (comma followed by more expressions then equals)
258 if p.check(token.Comma) {
259 var lhsList []*ast.Node
260 lhsList = append(lhsList, left)
261-
262+
263 // Parse comma-separated lvalues
264 for p.match(token.Comma) {
265 expr := p.parseTernaryExpr()
266 lhsList = append(lhsList, expr)
267 }
268-
269+
270 // Check if we have an assignment operator
271 if op := p.current.Type; op >= token.Eq && op <= token.EqShr {
272 // Validate all lhs expressions are lvalues
273@@ -1152,10 +1166,10 @@ func (p *Parser) parseAssignmentExpr() *ast.Node {
274 util.Error(p.current, "Invalid target for assignment")
275 }
276 }
277-
278+
279 tok := p.current
280 p.advance()
281-
282+
283 // Parse comma-separated rvalues
284 var rhsList []*ast.Node
285 for {
286@@ -1165,21 +1179,21 @@ func (p *Parser) parseAssignmentExpr() *ast.Node {
287 break
288 }
289 }
290-
291+
292 // Check that number of lhs and rhs match
293 if len(lhsList) != len(rhsList) {
294 util.Error(tok, "Mismatched number of variables and values in assignment (%d vs %d)", len(lhsList), len(rhsList))
295 }
296-
297+
298 return ast.NewMultiAssign(tok, op, lhsList, rhsList)
299 }
300-
301+
302 // Not a multi-assignment, backtrack and treat as comma expression
303 p.pos = startPos
304 p.current = startCurrent
305 left = p.parseTernaryExpr()
306 }
307-
308+
309 // Regular single assignment
310 if op := p.current.Type; op >= token.Eq && op <= token.EqShr {
311 if !isLValue(left) {
312@@ -1225,26 +1239,26 @@ func (p *Parser) parseBinaryExpr(minPrec int) *ast.Node {
313 }
314
315 func (p *Parser) parseUnaryExpr() *ast.Node {
316- tok := p.current
317- if p.match(token.Not, token.Complement, token.Minus, token.Plus, token.Inc, token.Dec, token.Star, token.And) {
318- op, opToken := p.previous.Type, p.previous
319- operand := p.parseUnaryExpr()
320-
321- if op == token.Star {
322- return ast.NewIndirection(tok, operand)
323- }
324- if op == token.And {
325- if !isLValue(operand) {
326- util.Error(opToken, "Address-of operator '&' requires an l-value")
327- }
328- return ast.NewAddressOf(tok, operand)
329- }
330- if (op == token.Inc || op == token.Dec) && !isLValue(operand) {
331- util.Error(opToken, "Prefix '++' or '--' requires an l-value")
332- }
333- return ast.NewUnaryOp(tok, op, operand)
334- }
335- return p.parsePostfixExpr()
336+ tok := p.current
337+ if p.match(token.Not, token.Complement, token.Minus, token.Plus, token.Inc, token.Dec, token.Star, token.And) {
338+ op, opToken := p.previous.Type, p.previous
339+ operand := p.parseUnaryExpr()
340+
341+ if op == token.Star {
342+ return ast.NewIndirection(tok, operand)
343+ }
344+ if op == token.And {
345+ if !isLValue(operand) {
346+ util.Error(opToken, "Address-of operator '&' requires an l-value")
347+ }
348+ return ast.NewAddressOf(tok, operand)
349+ }
350+ if (op == token.Inc || op == token.Dec) && !isLValue(operand) {
351+ util.Error(opToken, "Prefix '++' or '--' requires an l-value")
352+ }
353+ return ast.NewUnaryOp(tok, op, operand)
354+ }
355+ return p.parsePostfixExpr()
356 }
357
358 func (p *Parser) parsePostfixExpr() *ast.Node {
+5,
-5
1@@ -3,7 +3,7 @@ extrn printf, malloc;
2 type struct Point {
3 x int;
4 y int;
5- name byte*;
6+ name *byte;
7 };
8
9 type enum Color {
10@@ -128,9 +128,9 @@ void demo_pointer_arrays() {
11 printf("\nPointer arrays:\n");
12
13 int values[3];
14- int* int_ptr_array[3];
15- byte* string_array[3];
16- void* void_ptr_array[3];
17+ *int int_ptr_array[3];
18+ *byte string_array[3];
19+ *void void_ptr_array[3];
20
21 values[0] = 42;
22 values[1] = 84;
23@@ -210,7 +210,7 @@ void demo_enum_arrays() {
24 void demo_struct_pointer_arrays() {
25 printf("\nStruct pointer arrays:\n");
26
27- Point *point_ptr_array[2];
28+ *Point point_ptr_array[2];
29
30 point_ptr_array[0] = malloc(sizeof(Point));
31 point_ptr_array[1] = malloc(sizeof(Point));
+2,
-2
1@@ -9,8 +9,8 @@ main() {
2 printf("Function-style casts: a=%d, int(a)=%d, (int(a)+1)=%d\n", a, b, c);
3
4 ptr := &a;
5- byte_ptr := (byte*)ptr;
6- int_ptr := (int*)byte_ptr;
7+ byte_ptr := (*byte)ptr;
8+ int_ptr := (*int)byte_ptr;
9 value := *int_ptr;
10
11 printf("Pointer casts work: value=%d\n", value);
+2,
-2
1@@ -3,10 +3,10 @@ type struct Inner {
2 };
3
4 type struct Outer {
5- inner Inner*;
6+ inner *Inner;
7 };
8
9-Outer* createOuter(val int) {
10+*Outer createOuter(val int) {
11 auto i = Inner{value: val};
12 auto o = Outer{inner: &i};
13 return (&o);
+2,
-2
1@@ -22,12 +22,12 @@ Shape create_shape(c Color, x int, y int) {
2 }
3
4 void print_shape(s Shape) {
5- color_names := []byte*{ "RED", "GREEN", "BLUE", "YELLOW" };
6+ color_names := []*byte{ "RED", "GREEN", "BLUE", "YELLOW" };
7 printf("Shape: %s at (%d, %d)\n",
8 color_names[s.shape_color], s.x_pos, s.y_pos);
9 }
10
11-void move_shape(s Shape*, dx int, dy int) {
12+void move_shape(s *Shape, dx int, dy int) {
13 s.x_pos = s.x_pos + dx;
14 s.y_pos = s.y_pos + dy;
15 }