Skip to content

Commit

Permalink
Merge af54834 into 7a2ea96
Browse files Browse the repository at this point in the history
  • Loading branch information
deavmi committed Mar 27, 2024
2 parents 7a2ea96 + af54834 commit 1910b4c
Show file tree
Hide file tree
Showing 35 changed files with 3,342 additions and 648 deletions.
8 changes: 6 additions & 2 deletions dub.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
"copyright": "Copyright © 2021-2023, Tristan B. Kildaire",
"dependencies": {
"gogga": "~>0.1.0",
"jcli": "0.25.0-beta.3"
"jcli": "0.25.0-beta.3",
"niknaks": ">=0.9.8"
},
"description": "The official Tristan language compiler project",
"homepage": "http://deavmi.assigned.network/projects/tlang",
"license": "GPLv3",
"name": "tlang",
"homepage": "http://deavmi.assigned.network/projects/tlang"
"versions": [
"DBG_MODMAN"
]
}
2 changes: 1 addition & 1 deletion extern_test.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#1/bin/sh
#!/bin/sh

# Compile C to object file as library to link in
gcc source/tlang/testing/file_io.c -c -o file_io.o
Expand Down
13 changes: 13 additions & 0 deletions scratch/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
library:
gcc -c library.c -o library.o

clean:
rm library.o
rm main.o
rm main

main:
gcc -c main.c library.o -o main.o

exec:
gcc main.o library.o -o main
4 changes: 4 additions & 0 deletions scratch/library.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
int myFunc(int x)
{
return x*4;
}
9 changes: 9 additions & 0 deletions scratch/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
extern int myFunc(int);

#include<stdio.h>

int main()
{
int result = myFunc(4);
printf("myFunc(4): %d\n", result);
}
93 changes: 93 additions & 0 deletions small_doc_modules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
Module management
=================

It is deserving of its own chapter due to the complexities involved in the system - that is _the module management_ system. There are certain aspects to it which are allured to in other chapters such as the _resolution process_, the _code emit process with `DGen`_ and so forth. Due to this I will therefore only mention new information here rather than re-iterate all of that which belongs squarely in the documentation for those components of the compiler.

## Introduction

It is worth first defining what a _module_ is and hwo this relates to the compiler at large. Firstly a _program_ (see `Program`) is made up of one or more _modules_ (see `Module`).

A module can contain code such as global variable definitions, import statements, function definitions to name a few. Every module has a name within the given program and these names must be unique (TODO: check if that is enforced).

---

Below we show the directory structure of an example program that could be compiled:

```bash
source/tlang/testing/modules/
├── a.t
├── b.t
├── niks
│   └── c.t
```

Each of these files within the directory shown above is now shown below so you can see their contents, next to it we provide their module names as well (TODO: Ensure these match on `parse()` enter):

##### Module `a` at file `a.t`

```d
module a;
import niks.c;
import b;
int main()
{
int value = b.doThing();
return value;
}
```

##### Module `b` at file `b.t`

```d
module b;
import a;
int doThing()
{
int local = 0;
for(int i = 0; i < 10; i=i+1)
{
local = local +i;
}
return local;
}
```

##### Module `niks.c` at file `niks/c.t`

```d
module niks.c;
import a;
void k()
{
}
```

---

You could then go ahead and compile such a program by specifying the entrypoint module:

```bash
# Compile module a
./tlang compile source/tlang/testing/modules/a.t
```

Then running it, our code should return with an exit code of `45` due to what we implemented in the `b` module and how we used it in `a` which had our `main()` method:

```bash
# Run the output executable
./tlang.out

# Print the exit code
echo $?
```

> Note, the module you specify on the command-line will have its directory used as the base search path for the rest of the modules. Therefore specifying `a.t` or `b.t` is fine as they reside in the same directory whereby `niks/` can be found ut this is not true if you compiles `niks/c.t` as that would only see the search directory from `niks/` downwards - upwards searching does **not** occur
16 changes: 5 additions & 11 deletions source/tlang/commandline/commands.d
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public enum VerbosityLevel
mixin template BaseCommand()
{
@ArgPositional("source file", "The source file to compile")
string sourceFile;
string sourceFile; // TODO: Should accept a list in the future maybe

@ArgNamed("verbose|v", "Verbosity level")
@(ArgConfig.optional)
Expand Down Expand Up @@ -149,7 +149,7 @@ struct compileCommand
/* Begin lexing process */
File outFile;
outFile.open(outputFilename, "w");
Compiler compiler = new Compiler(sourceText, outFile);
Compiler compiler = new Compiler(sourceText, sourceFile, outFile);

/* Setup general configuration parameters */
BaseCommandInit(compiler);
Expand All @@ -161,8 +161,6 @@ struct compileCommand

/* Perform parsing */
compiler.doParse();
// TODO: Do something with the returned module
auto modulel = compiler.getModule();

/* Perform typechecking/codegen */
compiler.doTypeCheck();
Expand Down Expand Up @@ -217,7 +215,7 @@ struct lexCommand
file.close();

/* Begin lexing process */
Compiler compiler = new Compiler(sourceText, File());
Compiler compiler = new Compiler(sourceText, sourceFile, File());

/* Setup general configuration parameters */
BaseCommandInit(compiler);
Expand Down Expand Up @@ -263,7 +261,7 @@ struct parseCommand
file.close();

/* Begin lexing process */
Compiler compiler = new Compiler(sourceText, File());
Compiler compiler = new Compiler(sourceText, sourceFile, File());

/* Setup general configuration parameters */
BaseCommandInit(compiler);
Expand All @@ -274,8 +272,6 @@ struct parseCommand

/* Perform parsing */
compiler.doParse();
// TODO: Do something with the returned module
auto modulel = compiler.getModule();
}
catch(TError t)
{
Expand Down Expand Up @@ -312,7 +308,7 @@ struct typecheckCommand
file.close();

/* Begin lexing process */
Compiler compiler = new Compiler(sourceText, File());
Compiler compiler = new Compiler(sourceText, sourceFile, File());

/* Setup general configuration parameters */
BaseCommandInit(compiler);
Expand All @@ -323,8 +319,6 @@ struct typecheckCommand

/* Perform parsing */
compiler.doParse();
// TODO: Do something with the returned module
auto modulel = compiler.getModule();

/* Perform typechecking/codegen */
compiler.doTypeCheck();
Expand Down
44 changes: 19 additions & 25 deletions source/tlang/compiler/codegen/emit/core.d
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import std.range : walkLength;
import gogga;
import std.conv : to;
import tlang.compiler.configuration : CompilerConfiguration;
import tlang.compiler.codegen.mapper.core : SymbolMapper;
import tlang.compiler.codegen.mapper.api : SymbolMapperV2;

/**
* TODO: Perhaps have an interface that can emit(Context/Parent, Statement)
Expand All @@ -24,7 +24,7 @@ public abstract class CodeEmitter
protected TypeChecker typeChecker;
protected File file;
protected CompilerConfiguration config;
protected SymbolMapper mapper;
protected SymbolMapperV2 mapper;

/**
* The selected queue is the queue to be used
Expand All @@ -43,23 +43,28 @@ public abstract class CodeEmitter

private ulong queueCursor = 0;

public final void selectQueue(QueueType queueType, string funcDefName = "")
public final void selectQueue(Module owner, QueueType queueType, string funcDefName = "")
{
// Move the cursor back to the starting position
resetCursor();

if(queueType == QueueType.ALLOC_QUEUE)
{
selectedQueue = initQueue;
selectedQueue = this.typeChecker.getInitQueue(owner);
}
else if(queueType == QueueType.GLOBALS_QUEUE)
{
selectedQueue = globalCodeQueue;
selectedQueue = this.typeChecker.getGlobalCodeQueue(owner);
}
else
{
//TODO: Ensure valid name by lookup via tc

// Get the function definitions of the current module
functionBodyInstrs = this.typeChecker.getFunctionBodyCodeQueues(owner);

// Select the function definition by name from it
// and make that the current code queue
selectedQueue = functionBodyInstrs[funcDefName];
}
}
Expand Down Expand Up @@ -108,43 +113,32 @@ public abstract class CodeEmitter
return selectedQueue.length;
}

/**
* Required queues
*/
private Instruction[] initQueue;
private Instruction[] globalCodeQueue;

/**
* Required queues (maps to them)
*/
private Instruction[][string] functionBodyInstrs;

public final ulong getFunctionDefinitionsCount()
public final ulong getFunctionDefinitionsCount(Module owner)
{
// Get the function definitions of the current module
functionBodyInstrs = this.typeChecker.getFunctionBodyCodeQueues(owner);

return functionBodyInstrs.keys().length;
}

public final string[] getFunctionDefinitionNames()
public final string[] getFunctionDefinitionNames(Module owner)
{
// Get the function definitions of the current module
functionBodyInstrs = this.typeChecker.getFunctionBodyCodeQueues(owner);

return functionBodyInstrs.keys();
}

// TODO: Add allow for custom symbol mapper, use an interface or rather base class mechanism for it
this(TypeChecker typeChecker, File file, CompilerConfiguration config, SymbolMapper mapper)
this(TypeChecker typeChecker, File file, CompilerConfiguration config, SymbolMapperV2 mapper)
{
this.typeChecker = typeChecker;

/* Extract the allocation queue, the code queue */
initQueue = typeChecker.getInitQueue();
globalCodeQueue = typeChecker.getGlobalCodeQueue();

/* Extract the function definitions string-queue mapping */
functionBodyInstrs = typeChecker.getFunctionBodyCodeQueues();
gprintln("CodeEmitter: Got number of function defs: "~to!(string)(functionBodyInstrs));

this.file = file;
this.config = config;

this.mapper = mapper;
}

Expand Down
Loading

0 comments on commit 1910b4c

Please sign in to comment.