Skip to content

Commit 0503b1c

Browse files
committed
better list support and added to readme
1 parent 92075d7 commit 0503b1c

7 files changed

Lines changed: 51 additions & 17 deletions

File tree

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ This is a list of features that are currently implemented or planned for the fut
2727
- [x] **Double**.
2828
- [x] **String**.
2929
- [x] **Boolean**: Booleans do not have a type. Other types are evaluated to be truthy or falsy. Falsy values are `0`, `0.0`, `""`.
30-
- [ ] **Array**.
30+
- [x] **List**: Statically typed lists. Only `int`, `double`, and `str` are supported for now.
3131
- [ ] **Struct**: User-defined data types.
3232
- [x] **Comments**: Single-line comments with `#`.
3333
- [x] **String operations**:
@@ -209,6 +209,16 @@ func main() {
209209
math:acos(1.0);
210210
math:asin(0.0);
211211
math:atan(0.0);
212+
213+
# Lists are statically typed, and the type must be specified when creating a list
214+
# Only 'int', 'double', and 'str' are supported for now
215+
let myList list<int> = [1, 2, 3, 4, 5];
216+
# You can also create empty lists
217+
let myList2 list<int> = [];
218+
219+
# You can access or assign list elements using the [] operator
220+
myList[0] = 10;
221+
mcb:print(myList[0]);
212222
}
213223
```
214224

example/src/main.mcb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ func fizbuzz(n int) {
1414
# since for/while loops aren't supported yet, here is a cut down version of the fizzbuzz function
1515
# that evaluates a single value at a time instead of all the numbers up to n
1616
if (n % 3 == 0 and n % 5 == 0) {
17-
mcb:print("FizzBuzz");
17+
mcb:print("FizzBuzz!");
1818
} else if (n % 3 == 0) {
1919
mcb:print("Fizz");
2020
} else if (n % 5 == 0) {
@@ -87,4 +87,15 @@ func main() {
8787
math:acos(1.0);
8888
math:asin(0.0);
8989
math:atan(0.0);
90+
91+
# Lists are statically typed, and the type must be specified when creating a list
92+
# Only 'int', 'double', and 'str' are supported for now
93+
let myList list<int> = [1, 2, 3, 4, 5];
94+
# You can also create empty lists
95+
let myList2 list<int> = [];
96+
97+
# You can access or assign list elements using the [] operator
98+
myList[0] = 42;
99+
mcb:print("myList = " + myList);
100+
mcb:print("myList2 = " + myList2);
90101
}

internal/parser/statements.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ func (p *Parser) letDeclaration() (statements.Stmt, error) {
8787
return nil, err
8888
}
8989
if initializer != nil && initializer.ReturnType() != varType {
90-
return nil, p.error(p.peekCount(-2), fmt.Sprintf("Cannot assign %s to %s.", initializer.ReturnType(), varType))
90+
if !(p.isListType(varType) && initializer.ReturnType() == expressions.VoidType) {
91+
return nil, p.error(p.peekCount(-2), fmt.Sprintf("Cannot assign %s to %s.", initializer.ReturnType(), varType))
92+
}
9193
}
9294
p.variables[p.currentScope] = append(p.variables[p.currentScope], statements.VarDef{
9395
Name: name.Lexeme,
@@ -102,10 +104,10 @@ func (p *Parser) letDeclaration() (statements.Stmt, error) {
102104

103105
func (p *Parser) variableAssignment() (statements.Stmt, error) {
104106
name := p.previous()
105-
hasIndex := false
106107
var index expressions.Expr
108+
var err error
107109
if p.match(tokens.BracketOpen) {
108-
index, err := p.expression()
110+
index, err = p.expression()
109111
if err != nil {
110112
return nil, err
111113
}
@@ -116,12 +118,11 @@ func (p *Parser) variableAssignment() (statements.Stmt, error) {
116118
if index.ReturnType() != expressions.IntType {
117119
return nil, p.error(p.peek(), fmt.Sprintf("Index must be of type %s.", expressions.IntType))
118120
}
119-
if p.isStruct(name) {
121+
if !p.isList(name) {
120122
return nil, p.error(name, fmt.Sprintf("Cannot index type %s.", p.getType(name)))
121123
}
122-
hasIndex = true
123124
}
124-
_, err := p.consume(tokens.Equal, "Expected '=' after variable name.")
125+
_, err = p.consume(tokens.Equal, "Expected '=' after variable name.")
125126
if err != nil {
126127
return nil, err
127128
}
@@ -133,10 +134,7 @@ func (p *Parser) variableAssignment() (statements.Stmt, error) {
133134
if err != nil {
134135
return nil, err
135136
}
136-
if hasIndex {
137-
return statements.VariableAssignmentStmt{Name: name, Index: &index, Value: value}, nil
138-
}
139-
return statements.VariableAssignmentStmt{Name: name, Value: value}, nil
137+
return statements.VariableAssignmentStmt{Name: name, Value: value, Index: index}, nil
140138
}
141139

142140
func (p *Parser) functionDeclaration() (statements.Stmt, error) {

internal/parser/utils.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func (p *Parser) getType(name tokens.Token) interfaces.ValueType {
115115
return ""
116116
}
117117

118-
func (p *Parser) isStruct(name tokens.Token) bool {
118+
func (p *Parser) isList(name tokens.Token) bool {
119119
for _, v := range p.variables {
120120
for _, def := range v {
121121
if def.Name == name.Lexeme {
@@ -140,6 +140,19 @@ func (p *Parser) isStruct(name tokens.Token) bool {
140140
return false
141141
}
142142

143+
func (p *Parser) isListType(varType interfaces.ValueType) bool {
144+
switch varType {
145+
case expressions.ListIntType:
146+
return true
147+
case expressions.ListStringType:
148+
return true
149+
case expressions.ListDoubleType:
150+
return true
151+
default:
152+
return false
153+
}
154+
}
155+
143156
func (p *Parser) getListType(valueType interfaces.ValueType) interfaces.ValueType {
144157
switch valueType {
145158
case expressions.IntType:
@@ -148,6 +161,8 @@ func (p *Parser) getListType(valueType interfaces.ValueType) interfaces.ValueTyp
148161
return expressions.ListStringType
149162
case expressions.DoubleType:
150163
return expressions.ListDoubleType
164+
case expressions.VoidType:
165+
return expressions.VoidType
151166
default:
152167
log.Fatalf("Unsupported type for list: %s", valueType)
153168
}

internal/statements/variableAssignment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77

88
type VariableAssignmentStmt struct {
99
Name tokens.Token
10-
Index *expressions.Expr
10+
Index expressions.Expr
1111
Value expressions.Expr
1212
}
1313

internal/visitors/compiler/compiler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ func (c *Compiler) createFunctionTags() {
229229
}
230230

231231
func (c *Compiler) error(location interfaces.SourceLocation, message string) {
232-
log.Errorf("[Position %d:%d] Error at '%s':\n", location.Row+1, location.Col+1, message)
232+
log.Errorf("[Position %d:%d] Error: %s\n", location.Row+1, location.Col+1, message)
233233
}
234234

235235
func (c *Compiler) newRegister(regName string) string {

internal/visitors/compiler/statements.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,13 @@ func (c *Compiler) VisitVariableAssignment(stmt statements.VariableAssignmentStm
9393
cmd := ""
9494
isIndexedAssignment := stmt.Index != nil
9595
if stmt.Value.ReturnType() != c.getReturnType(stmt.Name.Lexeme) && !isIndexedAssignment {
96-
log.Fatalf("Assignment type mismatch: %v != %v\n", stmt.Value.ReturnType(), c.getReturnType(stmt.Name.Lexeme))
96+
c.error(stmt.Name.SourceLocation, fmt.Sprintf("Assignment type mismatch: %v != %v", c.getReturnType(stmt.Name.Lexeme), stmt.Value.ReturnType()))
9797
}
9898
cmd += stmt.Value.Accept(c).(string)
9999
valueReg := ops.Cs(c.newRegister(ops.RX))
100100
cmd += c.opHandler.Move(ops.Cs(ops.RX), valueReg)
101101
if isIndexedAssignment {
102-
cmd += (*stmt.Index).Accept(c).(string)
102+
cmd += stmt.Index.Accept(c).(string)
103103
indexReg := ops.Cs(c.newRegister(ops.RX))
104104
cmd += c.opHandler.Move(ops.Cs(ops.RX), indexReg)
105105
cmd += c.opHandler.SetListIndex(ops.Cs(stmt.Name.Lexeme), indexReg, valueReg)

0 commit comments

Comments
 (0)