Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/semantic-analyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,22 @@ class SemanticAnalyzer {
case 'StructDeclaration':
// Declare struct name
this.declare(stmt.name);
// Check struct fields for List/Map usage on AVR boards
if (this.config && this.config.isAVRBoard()) {
if (stmt.fields) {
stmt.fields.forEach(field => {
if (field.type && RESTRICTED_COLLECTION_TYPES.includes(field.type)) {
const board = this.config.options.board;
this.addError(
`Collection type '${field.type}' is not supported on AVR targets (${board}) due to insufficient RAM.\n` +
` AVR boards have very limited memory and cannot support std::vector and std::map.\n` +
` Consider using arrays or simpler data structures, or target a board with more RAM (e.g., ESP32).`,
stmt.line
);
}
});
}
}
break;

case 'FunctionDeclaration':
Expand Down Expand Up @@ -339,6 +355,19 @@ class SemanticAnalyzer {
// Declare all properties
if (stmt.properties) {
stmt.properties.forEach(prop => {
// Check for List/Map usage on AVR boards
if (this.config && this.config.isAVRBoard()) {
if (prop.propertyType && RESTRICTED_COLLECTION_TYPES.includes(prop.propertyType)) {
const board = this.config.options.board;
this.addError(
`Collection type '${prop.propertyType}' is not supported on AVR targets (${board}) due to insufficient RAM.\n` +
` AVR boards have very limited memory and cannot support std::vector and std::map.\n` +
` Consider using arrays or simpler data structures, or target a board with more RAM (e.g., ESP32).`,
stmt.line
);
}
}

this.declare(prop.name);
if (prop.init) {
this.analyzeExpression(prop.init);
Expand Down
165 changes: 165 additions & 0 deletions tests/semantic-analyzer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -455,4 +455,169 @@ describe('Semantic Analyzer - AVR Board Restrictions', () => {
expect(result.error).toContain('Collection type \'List\' is not supported on AVR targets');
expect(result.error).toContain('Collection type \'Map\' is not supported on AVR targets');
});

test('should reject List type in class field on arduino_uno', () => {
const source = `
@main
config {
board: arduino_uno,
clock: 16MHz
}

class DataLogger {
mut List data

constructor() {
self.data = new List()
}

fn addReading(int value) {
self.data.push(value)
}
}

on start {
mut DataLogger logger = new DataLogger()
}
`;

const result = compile(source);
expect(result.success).toBe(false);
expect(result.error).toContain('Collection type \'List\' is not supported on AVR targets');
expect(result.error).toContain('arduino_uno');
expect(result.error).toContain('insufficient RAM');
});

test('should reject Map type in class field on arduino_uno', () => {
const source = `
@main
config {
board: arduino_uno,
clock: 16MHz
}

class Configuration {
mut Map settings

constructor() {
self.settings = new Map()
}

fn setSetting(int key, int value) {
self.settings.set(key, value)
}
}

on start {
mut Configuration cfg = new Configuration()
}
`;

const result = compile(source);
expect(result.success).toBe(false);
expect(result.error).toContain('Collection type \'Map\' is not supported on AVR targets');
expect(result.error).toContain('arduino_uno');
expect(result.error).toContain('insufficient RAM');
});

test('should allow List type in class field on esp32', () => {
const source = `
@main
config {
board: esp32,
clock: 16MHz
}

class DataLogger {
mut List data

constructor() {
self.data = new List()
}

fn addReading(int value) {
self.data.push(value)
}
}

on start {
mut DataLogger logger = new DataLogger()
}
`;

const result = compile(source);
expect(result.success).toBe(true);
});

test('should reject List type in struct field on arduino_uno', () => {
const source = `
@main
config {
board: arduino_uno,
clock: 16MHz
}

struct DataPoint {
List values
int timestamp
}

on start {
print("test")
}
`;

const result = compile(source);
expect(result.success).toBe(false);
expect(result.error).toContain('Collection type \'List\' is not supported on AVR targets');
expect(result.error).toContain('arduino_uno');
expect(result.error).toContain('insufficient RAM');
});

test('should reject Map type in struct field on arduino_uno', () => {
const source = `
@main
config {
board: arduino_uno,
clock: 16MHz
}

struct Config {
Map settings
int version
}

on start {
print("test")
}
`;

const result = compile(source);
expect(result.success).toBe(false);
expect(result.error).toContain('Collection type \'Map\' is not supported on AVR targets');
expect(result.error).toContain('arduino_uno');
expect(result.error).toContain('insufficient RAM');
});

test('should allow List type in struct field on esp32', () => {
const source = `
@main
config {
board: esp32,
clock: 16MHz
}

struct DataPoint {
List values
int timestamp
}

on start {
print("test")
}
`;

const result = compile(source);
expect(result.success).toBe(true);
});
});