Skip to content
Merged
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
10 changes: 8 additions & 2 deletions src/codegen/expressions/method-calls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -736,8 +736,11 @@ export class MethodCallGenerator {
const mapMeta = this.ctx.symbolTable.getMapMetadata(varName);

if (mapMeta && mapMeta.keyType === "string") {
const mapAlloca = this.ctx.symbolTable.getAlloca(varName);
let mapAlloca = this.ctx.symbolTable.getAlloca(varName);
if (mapAlloca) {
if (mapAlloca.startsWith("@")) {
mapAlloca = this.ctx.emitLoad("%StringMap*", mapAlloca);
}
if (method === "set") {
const keyValue = this.ctx.generateExpression(expr.args[0], params);
const valueValue = this.ctx.generateExpression(expr.args[1], params);
Expand Down Expand Up @@ -907,8 +910,11 @@ export class MethodCallGenerator {
const setValueType = this.ctx.symbolTable.getSetValueType(varName);

if (setValueType && setValueType === "string") {
const setAlloca = this.ctx.symbolTable.getAlloca(varName);
let setAlloca = this.ctx.symbolTable.getAlloca(varName);
if (setAlloca) {
if (setAlloca.startsWith("@")) {
setAlloca = this.ctx.emitLoad("%StringSet*", setAlloca);
}
if (method === "add") {
const valueValue = this.ctx.generateExpression(expr.args[0], params);
return this.ctx.stringSetGen.generateStringSetAdd(setAlloca, valueValue);
Expand Down
26 changes: 16 additions & 10 deletions src/codegen/expressions/variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,25 +80,31 @@ export class VariableExpressionGenerator {

// Check if it's a map variable
if (this.ctx.symbolTable.isMap(name)) {
const allocaReg = this.ctx.getVariableAlloca(name)!;
let allocaReg = this.ctx.getVariableAlloca(name)!;
const mapMeta = this.ctx.symbolTable.getMapMetadata(name);
if (mapMeta && mapMeta.keyType === "string") {
this.ctx.setVariableType(allocaReg, "%StringMap*");
} else {
this.ctx.setVariableType(allocaReg, "%Map*");
const mapType = mapMeta && mapMeta.keyType === "string" ? "%StringMap*" : "%Map*";
if (allocaReg.startsWith("@")) {
const loaded = this.ctx.nextTemp();
this.ctx.emit(`${loaded} = load ${mapType}, ${mapType}* ${allocaReg}`);
this.ctx.setVariableType(loaded, mapType);
return loaded;
}
this.ctx.setVariableType(allocaReg, mapType);
return allocaReg;
}

// Check if it's a set variable
if (this.ctx.symbolTable.isSet(name)) {
const allocaReg = this.ctx.getVariableAlloca(name)!;
let allocaReg = this.ctx.getVariableAlloca(name)!;
const setValueType = this.ctx.symbolTable.getSetValueType(name);
if (setValueType === "string") {
this.ctx.setVariableType(allocaReg, "%StringSet*");
} else {
this.ctx.setVariableType(allocaReg, "%Set*");
const setType = setValueType === "string" ? "%StringSet*" : "%Set*";
if (allocaReg.startsWith("@")) {
const loaded = this.ctx.nextTemp();
this.ctx.emit(`${loaded} = load ${setType}, ${setType}* ${allocaReg}`);
this.ctx.setVariableType(loaded, setType);
return loaded;
}
this.ctx.setVariableType(allocaReg, setType);
return allocaReg;
}

Expand Down
48 changes: 42 additions & 6 deletions src/codegen/llvm-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2178,12 +2178,48 @@ export class LLVMGenerator extends BaseGenerator implements IGeneratorContext {
continue;
}
} else if (isMap) {
this.emitError(
"Map operations at the top level are not supported — wrap in a function",
undefined,
"function main() { const " + name + " = new Map(...); ... } main();",
);
return "";
let isStringMap = false;
let mapValueType = "string";
if (stmt.declaredType) {
const dt = stmt.declaredType;
if (dt.indexOf("Map<string") !== -1) {
isStringMap = true;
const parsed = parseMapTypeString(dt);
if (parsed) mapValueType = parsed.valueType;
}
}
if (!isStringMap && stmt.value) {
const mapNode = stmt.value as MapNode;
if (mapNode.keyType === "string") {
isStringMap = true;
mapValueType = mapNode.valueType || "string";
}
}
if (isStringMap) {
llvmType = "%StringMap*";
kind = SymbolKind.Map;
defaultValue = "null";
const llvmValueType = mapValueType === "number" ? "double" : "i8*";
ir += `@${name} = global ${llvmType} ${defaultValue}` + "\n";
this.globalVariables.set(name, { llvmType, kind, initialized: false });
this.defineVariableWithMetadata(
name,
`@${name}`,
llvmType,
kind,
"global",
createMapMetadataSymbol({
keyType: "string",
valueType: mapValueType,
llvmKeyType: "i8*",
llvmValueType,
}),
);
continue;
}
llvmType = "%Map*";
kind = SymbolKind.Map;
defaultValue = "null";
} else if (isSet) {
let isStringSet = false;
if (stmt.declaredType) {
Expand Down
5 changes: 0 additions & 5 deletions tests/fixtures/data-structures/map-global-scope-error.ts

This file was deleted.

8 changes: 8 additions & 0 deletions tests/fixtures/data-structures/map-global-scope.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @test-description: global scope map operations work correctly
const m = new Map<string, string>();
m.set("hello", "world");
m.set("foo", "bar");

if (m.get("hello") === "world" && m.get("foo") === "bar" && m.size === 2) {
console.log("TEST_PASSED");
}
9 changes: 9 additions & 0 deletions tests/fixtures/data-structures/set-global-scope.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @test-description: global scope set operations work correctly
const s = new Set<string>();
s.add("hello");
s.add("world");
s.add("hello");

if (s.has("hello") && s.has("world") && s.size === 2) {
console.log("TEST_PASSED");
}
Loading