Compare commits

..

14 Commits
lsp ... main

24 changed files with 925 additions and 274 deletions

20
Cargo.lock generated
View File

@ -654,7 +654,7 @@ checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
[[package]] [[package]]
name = "reid" name = "reid"
version = "1.0.0-beta.2" version = "1.0.0-beta.3"
dependencies = [ dependencies = [
"colored", "colored",
"reid-lib", "reid-lib",
@ -662,15 +662,7 @@ dependencies = [
] ]
[[package]] [[package]]
name = "reid-lib" name = "reid-language-server"
version = "1.0.0-beta.2"
dependencies = [
"llvm-sys",
"thiserror",
]
[[package]]
name = "reid-lsp"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"dashmap 6.1.0", "dashmap 6.1.0",
@ -680,6 +672,14 @@ dependencies = [
"tower-lsp", "tower-lsp",
] ]
[[package]]
name = "reid-lib"
version = "1.0.0-beta.3"
dependencies = [
"llvm-sys",
"thiserror",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.26" version = "0.1.26"

View File

@ -71,9 +71,9 @@ Currently missing big features (TODOs) are:
Big features that I want later but are not necessary: Big features that I want later but are not necessary:
- ~~User-defined binary operations~~ (DONE) - ~~User-defined binary operations~~ (DONE)
- ~~Asymmetric binary operations (e.g. string + u32)~~ (DONE) - ~~Asymmetric binary operations (e.g. string + u32)~~ (DONE)
- Error handling - ~~Error handling~~ (Not Doing It)
- Lexing & parsing of whitespace and comments as well - ~~Lexing & parsing of whitespace and comments as well~~ (DONE)
- LSP implementation - ~~LSP implementation~~ (CRUCIAL FEATURES DONE)
Smaller features: Smaller features:
- ~~Hex-numbers~~ (DONE) - ~~Hex-numbers~~ (DONE)

View File

@ -1,12 +1,13 @@
// Main a
fn main() -> bool { (
return 144 == fibonacci(0xc); b
} )
x
// Fibonacci (
fn fibonacci(value: u16) -> u16 { (
if value <= 2 { c
return 1; xyz
} )
fibonacci(value - 1) + fibonacci(value - 2) )
} (
a

View File

@ -4,5 +4,6 @@ import std::print;
fn main() -> u8 { fn main() -> u8 {
let bytes = include_bytes!("./macro_easy_file.txt"); let bytes = include_bytes!("./macro_easy_file.txt");
print(String::new() + bytes.length()); print(String::new() + bytes.length());
return (bytes as *u8)[0]; print(String::new() + (include_bytes!("./macro_easy_file.txt") as *u8)[1] as u64);
return (include_bytes!("./macro_easy_file.txt") as *u8)[0];
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "reid-lib" name = "reid-lib"
version = "1.0.0-beta.2" version = "1.0.0-beta.3"
edition = "2024" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -610,30 +610,9 @@ impl Builder {
Instr::PtrToInt(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), Instr::PtrToInt(instr, ty) => instr.cast_to(self, &ty).map(|_| ()),
Instr::IntToPtr(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), Instr::IntToPtr(instr, ty) => instr.cast_to(self, &ty).map(|_| ()),
Instr::BitCast(..) => Ok(()), Instr::BitCast(..) => Ok(()),
Instr::ShiftRightLogical(_, rhs) => { Instr::ShiftRightLogical(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
let rhs_ty = rhs.get_type(&self)?; Instr::ShiftRightArithmetic(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
if rhs_ty.category() == TypeCategory::UnsignedInteger { Instr::ShiftLeft(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::ShiftRightArithmetic(_, rhs) => {
let rhs_ty = rhs.get_type(&self)?;
if rhs_ty.category() == TypeCategory::UnsignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::ShiftLeft(_, rhs) => {
let rhs_ty = rhs.get_type(&self)?;
if rhs_ty.category() == TypeCategory::UnsignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::GetGlobal(_) => Ok(()), Instr::GetGlobal(_) => Ok(()),
} }
} }

View File

@ -540,7 +540,7 @@ impl DebugTypeHolder {
field.pos.map(|p| p.line).unwrap_or(1), field.pos.map(|p| p.line).unwrap_or(1),
field.size_bits, field.size_bits,
0, 0,
1, field.offset,
field.flags.as_llvm(), field.flags.as_llvm(),
*debug.types.get(&field.ty).unwrap(), *debug.types.get(&field.ty).unwrap(),
) )

3
reid-lsp/.gitignore vendored
View File

@ -3,4 +3,5 @@ node_modules
dist dist
package-lock.json package-lock.json
pnpm-lock.yaml pnpm-lock.yaml
tsconfig.tsbuildinfo tsconfig.tsbuildinfo
*.vsix

View File

@ -1,5 +1,5 @@
[package] [package]
name = "reid-lsp" name = "reid-language-server"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"
@ -7,5 +7,5 @@ edition = "2024"
socket = "0.0.7" socket = "0.0.7"
tokio = { version = "1.47.0", features = ["full"] } tokio = { version = "1.47.0", features = ["full"] }
tower-lsp = "0.20.0" tower-lsp = "0.20.0"
reid = { path = "../reid", version = "1.0.0-beta.2", registry="gitea-teascade", features=[] } reid = { path = "../reid", version = "1.0.0-beta.3", registry="gitea-teascade", features=[] }
dashmap = "6.1.0" dashmap = "6.1.0"

View File

@ -1,71 +1 @@
# reid-lsp README # Reid Language Server
This is the README for your extension "reid-lsp". After writing up a brief description, we recommend including the following sections.
## Features
Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file.
For example if there is an image subfolder under your extension project workspace:
\!\[feature X\]\(images/feature-x.png\)
> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow.
## Requirements
If you have any requirements or dependencies, add a section describing those and how to install and configure them.
## Extension Settings
Include if your extension adds any VS Code settings through the `contributes.configuration` extension point.
For example:
This extension contributes the following settings:
* `myExtension.enable`: Enable/disable this extension.
* `myExtension.thing`: Set to `blah` to do something.
## Known Issues
Calling out known issues can help limit users opening duplicate issues against your extension.
## Release Notes
Users appreciate release notes as you update your extension.
### 1.0.0
Initial release of ...
### 1.0.1
Fixed issue #.
### 1.1.0
Added features X, Y, and Z.
---
## Following extension guidelines
Ensure that you've read through the extensions guidelines and follow the best practices for creating your extension.
* [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines)
## Working with Markdown
You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts:
* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux).
* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux).
* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets.
## For more information
* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown)
* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/)
**Enjoy!**

View File

@ -18,12 +18,20 @@ import {
let client: LanguageClient; let client: LanguageClient;
export function activate(context: ExtensionContext) { export function activate(context: ExtensionContext) {
const traceOutputChannel = window.createOutputChannel("Reid Language Server trace"); const configuration = workspace.getConfiguration('reid-language-server');
const command = process.env.SERVER_PATH || "reid-language-server"; let server_path: string = process.env.SERVER_PATH ?? configuration.get("language-server-path") ?? 'reid-language-server';
const regex = /\$(\w+)/;
while (regex.test(server_path)) {
let envVar = regex.exec(server_path)?.[1];
const envVal = envVar ? process.env[envVar] : undefined;
if (envVar === undefined || envVal === undefined) {
console.error(`No such environment variables as ${envVar}`);
}
server_path = server_path.replaceAll(`$${envVar}`, envVal ?? '');
}
const run: Executable = { const run: Executable = {
command, command: server_path,
options: { options: {
env: { env: {
...process.env, ...process.env,
@ -49,13 +57,15 @@ export function activate(context: ExtensionContext) {
// Create the language client and start the client. // Create the language client and start the client.
client = new LanguageClient( client = new LanguageClient(
'reid-lsp', 'reid-language-server',
'Reid Language Server', 'Reid Language Server',
serverOptions, serverOptions,
clientOptions clientOptions
); );
client.info(JSON.stringify(server_path));
client.info(`Loaded Reid Language Server from ${server_path}`);
client.info("hello");
workspace.onDidOpenTextDocument((e) => { workspace.onDidOpenTextDocument((e) => {
}); });

View File

@ -1,8 +1,11 @@
{ {
"name": "reid-lsp", "name": "reid-language-server",
"displayName": "Reid Language Server", "displayName": "Reid Language Server",
"description": "Language Server Extension for Reid", "description": "Language Server Extension for Reid",
"version": "0.0.1", "version": "0.1.0",
"repository": {
"url": "https://git.teascade.net/teascade"
},
"engines": { "engines": {
"vscode": "^1.102.0" "vscode": "^1.102.0"
}, },
@ -19,6 +22,9 @@
"id": "reid", "id": "reid",
"extensions": [ "extensions": [
".reid" ".reid"
],
"aliases": [
"Reid"
] ]
} }
], ],
@ -26,28 +32,25 @@
"type": "object", "type": "object",
"title": "reid-language-server", "title": "reid-language-server",
"properties": { "properties": {
"nrs-language-server.trace.server": { "reid-language-server.language-server-path": {
"type": "string", "type": "string",
"scope": "window", "scope": "window",
"enum": [ "default": "$HOME/.cargo/bin/reid-lsp",
"off", "description": "Path to the Reid Language Server executable"
"messages",
"verbose"
],
"enumDescriptions": [
"No traces",
"Error only",
"Full log"
],
"default": "off",
"description": "Traces the communication between VS Code and the language server."
} }
} }
} },
"grammars": [
{
"language": "reid",
"scopeName": "source.reid",
"path": "./syntaxes/grammar.json"
}
]
}, },
"scripts": { "scripts": {
"vscode:prepublish": "pnpm run package", "vscode:prepublish": "pnpm run package",
"compile": "webpack", "compile": "npx js-yaml syntaxes/grammar.yaml > syntaxes/grammar.json && webpack",
"watch": "webpack --watch", "watch": "webpack --watch",
"package": "webpack --mode production --devtool hidden-source-map", "package": "webpack --mode production --devtool hidden-source-map",
"compile-tests": "tsc -p . --outDir out", "compile-tests": "tsc -p . --outDir out",
@ -65,6 +68,7 @@
"@vscode/test-cli": "^0.0.11", "@vscode/test-cli": "^0.0.11",
"@vscode/test-electron": "^2.5.2", "@vscode/test-electron": "^2.5.2",
"eslint": "^9.25.1", "eslint": "^9.25.1",
"js-yaml": "^4.1.0",
"ts-loader": "^9.5.2", "ts-loader": "^9.5.2",
"typescript": "^5.8.3", "typescript": "^5.8.3",
"webpack": "^5.99.7", "webpack": "^5.99.7",

View File

@ -12,9 +12,9 @@ use reid::{compile_module, parse_module, perform_all_passes};
use tower_lsp::lsp_types::{ use tower_lsp::lsp_types::{
self, CompletionItem, CompletionOptions, CompletionParams, CompletionResponse, Diagnostic, DiagnosticSeverity, self, CompletionItem, CompletionOptions, CompletionParams, CompletionResponse, Diagnostic, DiagnosticSeverity,
DidChangeTextDocumentParams, DidOpenTextDocumentParams, Hover, HoverContents, HoverParams, HoverProviderCapability, DidChangeTextDocumentParams, DidOpenTextDocumentParams, Hover, HoverContents, HoverParams, HoverProviderCapability,
InitializeParams, InitializeResult, InitializedParams, MarkedString, MessageType, OneOf, Range, ServerCapabilities, InitializeParams, InitializeResult, InitializedParams, MarkedString, MarkupContent, MarkupKind, MessageType, OneOf,
TextDocumentItem, TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, Range, ServerCapabilities, TextDocumentItem, TextDocumentSyncCapability, TextDocumentSyncKind,
WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities, TextDocumentSyncOptions, WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities,
}; };
use tower_lsp::{Client, LanguageServer, LspService, Server, jsonrpc}; use tower_lsp::{Client, LanguageServer, LspService, Server, jsonrpc};
@ -91,24 +91,38 @@ impl LanguageServer for Backend {
None None
}; };
let ty = if let Some(token) = token { let (range, ty) = if let Some(token) = token {
if let Some(possible_ty) = self.types.get(&file_name).unwrap().get(token) { if let Some(possible_ty) = self.types.get(&file_name).unwrap().get(token) {
let start = token.position;
let end = token.position.add(token.token.len() as u32);
let range = Range {
start: lsp_types::Position {
line: (start.1 as i32 - 1).max(0) as u32,
character: (start.0 as i32 - 1).max(0) as u32,
},
end: lsp_types::Position {
line: (end.1 as i32 - 1).max(0) as u32,
character: (end.0 as i32 - 1).max(0) as u32,
},
};
if let Some(ty) = possible_ty.clone() { if let Some(ty) = possible_ty.clone() {
format!("{}", ty) (Some(range), format!("{}", ty))
} else { } else {
String::from("no type") (Some(range), String::from("None type"))
} }
} else { } else {
String::from("no token") (None, String::from("no type"))
} }
} else { } else {
String::from("no token") (None, String::from("no token"))
}; };
Ok(Some(Hover { let contents = HoverContents::Markup(MarkupContent {
contents: HoverContents::Scalar(MarkedString::String(format!("{}", ty))), kind: MarkupKind::Markdown,
range: None, value: format!("`{ty}`"),
})) });
Ok(Some(Hover { contents, range }))
} }
async fn did_open(&self, params: DidOpenTextDocumentParams) { async fn did_open(&self, params: DidOpenTextDocumentParams) {
@ -253,7 +267,10 @@ async fn main() {
pub fn find_type_in_context(module: &mir::Module, token_idx: usize) -> Option<TypeKind> { pub fn find_type_in_context(module: &mir::Module, token_idx: usize) -> Option<TypeKind> {
for import in &module.imports { for import in &module.imports {
if import.1.contains(token_idx) { if import.1.contains(token_idx) {
return None; return Some(TypeKind::CustomType(mir::CustomTypeKey(
"d".to_owned(),
SourceModuleId(1),
)));
} }
} }
for typedef in &module.typedefs { for typedef in &module.typedefs {
@ -272,6 +289,40 @@ pub fn find_type_in_context(module: &mir::Module, token_idx: usize) -> Option<Ty
} }
} }
for binop in &module.binop_defs {
if let Some(meta) = binop.block_meta() {
if !meta.contains(token_idx) {
continue;
}
} else {
continue;
}
return match &binop.fn_kind {
mir::FunctionDefinitionKind::Local(block, _) => find_type_in_block(&block, module.module_id, token_idx),
mir::FunctionDefinitionKind::Extern(_) => None,
mir::FunctionDefinitionKind::Intrinsic(_) => None,
};
}
for (_, function) in &module.associated_functions {
if !(function.signature() + function.block_meta()).contains(token_idx) {
continue;
}
for param in &function.parameters {
if param.meta.contains(token_idx) {
return Some(param.ty.clone());
}
}
return match &function.kind {
mir::FunctionDefinitionKind::Local(block, _) => find_type_in_block(&block, module.module_id, token_idx),
mir::FunctionDefinitionKind::Extern(_) => None,
mir::FunctionDefinitionKind::Intrinsic(_) => None,
};
}
for function in &module.functions { for function in &module.functions {
if !(function.signature() + function.block_meta()).contains(token_idx) { if !(function.signature() + function.block_meta()).contains(token_idx) {
continue; continue;
@ -294,7 +345,7 @@ pub fn find_type_in_context(module: &mir::Module, token_idx: usize) -> Option<Ty
pub fn find_type_in_block(block: &mir::Block, module_id: SourceModuleId, token_idx: usize) -> Option<TypeKind> { pub fn find_type_in_block(block: &mir::Block, module_id: SourceModuleId, token_idx: usize) -> Option<TypeKind> {
if !block.meta.contains(token_idx) { if !block.meta.contains(token_idx) {
return None; return Some(TypeKind::Bool);
} }
for statement in &block.statements { for statement in &block.statements {
@ -372,7 +423,7 @@ pub fn find_type_in_expr(expr: &mir::Expression, module_id: SourceModuleId, toke
Some(TypeKind::CustomType(mir::CustomTypeKey(name.clone(), module_id))) Some(TypeKind::CustomType(mir::CustomTypeKey(name.clone(), module_id)))
} }
mir::ExprKind::Literal(literal) => Some(literal.as_type()), mir::ExprKind::Literal(literal) => Some(literal.as_type()),
mir::ExprKind::BinOp(binary_operator, lhs, rhs, type_kind) => { mir::ExprKind::BinOp(_, lhs, rhs, type_kind) => {
if let Some(ty) = find_type_in_expr(lhs, module_id, token_idx) { if let Some(ty) = find_type_in_expr(lhs, module_id, token_idx) {
return Some(ty); return Some(ty);
} }
@ -431,7 +482,10 @@ pub fn find_type_in_expr(expr: &mir::Expression, module_id: SourceModuleId, toke
{ {
Some(*inner.clone()) Some(*inner.clone())
} else { } else {
None Some(TypeKind::CustomType(mir::CustomTypeKey(
"ä".to_owned(),
SourceModuleId(1),
)))
} }
} }
mir::ExprKind::CastTo(expression, type_kind) => { mir::ExprKind::CastTo(expression, type_kind) => {

View File

@ -0,0 +1,395 @@
{
"scopeName": "source.reid",
"patterns": [
{
"include": "#import"
},
{
"include": "#expression"
}
],
"repository": {
"import": {
"begin": "(import)\\s*",
"end": ";",
"beginCaptures": {
"1": {
"name": "keyword"
}
},
"endCaptures": {
"0": {
"name": "punctuation.semi.reid"
}
},
"patterns": [
{
"include": "#identifier"
},
{
"include": "#punctiation"
}
]
},
"punctuation": {
"patterns": [
{
"match": "::",
"name": "keyword.operator.namespace.reid"
},
{
"match": ";",
"name": "punctuation.semi.reid"
},
{
"match": ".",
"name": "punctuation.dot.reid"
},
{
"match": ",",
"name": "punctuation.comma.reid"
}
]
},
"expression": {
"patterns": [
{
"include": "#comment"
},
{
"include": "#fn-signature"
},
{
"include": "#common-type"
},
{
"include": "#binop-impl"
},
{
"include": "#type-impl"
},
{
"include": "#struct-definition"
},
{
"include": "#block"
},
{
"include": "#binop"
},
{
"include": "#namespace"
},
{
"include": "#cast"
},
{
"include": "#function-call"
},
{
"include": "#parenthesis"
},
{
"include": "#array"
},
{
"include": "#keywords"
},
{
"include": "#struct-expression"
},
{
"include": "#number-literal"
},
{
"include": "#string-literal"
},
{
"include": "#identifier"
},
{
"include": "#punctuation"
}
]
},
"comment": {
"match": "\\/\\/(.|\\/)*",
"name": "comment.line.double-slash.reid"
},
"fn-signature": {
"begin": "(fn)\\s*(\\w+)\\(",
"beginCaptures": {
"1": {
"name": "keyword.fn.reid"
},
"2": {
"name": "entity.name.function.reid"
}
},
"end": "\\)",
"patterns": [
{
"include": "#annotated-identifier"
},
{
"include": "#keywords"
},
{
"include": "#binop"
}
],
"endCaptures": {
"2": {
"name": "entity.name.type.reid"
}
}
},
"type-impl": {
"begin": "(impl)\\s* (\\w+)\\s* \\{\n",
"end": "\\}",
"captures": {
"1": {
"name": "keyword.impl.reid"
},
"2": {
"name": "entity.name.type"
}
},
"patterns": [
{
"include": "#expression"
}
]
},
"binop-impl": {
"begin": "(impl)\\s+(binop)\\s+\\(((.*)\\s*:\\s*(.*))\\)(.*)\\(((.*)\\s*:\\s*(.*))\\)\\s*->\\s*(\\w+)\\s*\\{",
"end": "\\}",
"beginCaptures": {
"1": {
"name": "keyword.impl.reid"
},
"2": {
"name": "keyword.impl.reid"
},
"4": {
"name": "variable.parameter.binop.reid"
},
"5": {
"name": "entity.name.type.parameter.binop.reid"
},
"6": {
"name": "keyword.operator.math.reid"
},
"8": {
"name": "variable.parameter.binop.reid"
},
"9": {
"name": "entity.name.type.parameter.binop.reid"
},
"10": {
"name": "entity.name.type.return.binop.reid"
}
},
"patterns": [
{
"include": "#expression"
}
]
},
"struct-definition": {
"begin": "(struct)\\s*(\\w+)\\s*\\{",
"end": "\\}",
"captures": {
"1": {
"name": "keyword.struct.reid"
},
"2": {
"name": "entity.name.type"
}
},
"patterns": [
{
"include": "#annotated-identifier"
}
]
},
"struct-expression": {
"begin": "([A-Z]\\w*)\\s*\\{",
"end": "\\}",
"captures": {
"1": {
"name": "entity.name.type.struct.reid"
}
},
"patterns": [
{
"include": "#expression"
}
]
},
"number-literal": {
"patterns": [
{
"match": "0x[0-9a-fA-F]+(\\.[0-9a-fA-F]+)?",
"name": "constant.hexadecimal"
},
{
"match": "0o[0-7]+(\\.[0-7]+)?",
"name": "constant.octal"
},
{
"match": "0b[01]+(\\.[01]+)?",
"name": "constant.binary"
},
{
"match": "[0-9]+(\\.[0-9]+)?",
"name": "constant.numeric"
}
]
},
"string-literal": {
"begin": "\"",
"end": "\"",
"name": "string.quoted.double",
"patterns": [
{
"match": "\\.",
"name": "constant.character.escape"
}
]
},
"block": {
"begin": "\\{",
"end": "\\}",
"patterns": [
{
"include": "#expression"
}
]
},
"namespace": {
"match": "(\\w+)(\\:\\:)",
"captures": {
"1": {
"name": "entity.name.function.reid"
},
"2": {
"name": "keyword.operator.namespace.reid"
}
}
},
"cast": {
"match": "(as)\\s+(\\w+)",
"captures": {
"1": {
"name": "keyword.cast.reid"
},
"2": {
"name": "entity.name.type.reid"
}
}
},
"function-call": {
"begin": "(\\w+)?\\(",
"end": "\\)",
"beginCaptures": {
"1": {
"name": "entity.name.function.reid"
}
},
"patterns": [
{
"include": "#expression"
}
]
},
"parenthesis": {
"begin": "\\(",
"end": "\\)",
"beginCaptures": {
"0": {
"name": "keyword.operator.parenthesis.reid"
}
},
"endCaptures": {
"0": {
"name": "keyword.operator.parenthesis.reid"
}
},
"patterns": [
{
"include": "#expression"
}
]
},
"annotated-identifier": {
"begin": "(\\w+)\\:",
"end": ",",
"beginCaptures": {
"1": {
"name": "variable.language.reid"
}
},
"patterns": [
{
"include": "#expression"
}
]
},
"identifier": {
"patterns": [
{
"match": "[A-Z]\\w*",
"name": "entity.name.type.reid"
},
{
"match": "\\w+",
"name": "variable.language.reid"
}
]
},
"keywords": {
"patterns": [
{
"match": "let|mut|pub|extern",
"name": "storage.type.reid"
},
{
"match": "if|return",
"name": "keyword.control"
},
{
"match": "self",
"name": "variable.language.self.reid"
}
]
},
"binop": {
"match": "\\<\\=|\\>\\=|\\=\\=|\\<|\\>|\\*|\\+|\\-|\\^|\\&\\&|\\&",
"name": "keyword.operator.math.reid"
},
"array": {
"begin": "\\[",
"end": "\\]",
"beginCaptures": {
"0": {
"name": "entity.name.type.array.reid"
}
},
"endCaptures": {
"0": {
"name": "entity.name.type.array.reid"
}
},
"patterns": [
{
"include": "#expression"
}
]
},
"common-type": {
"match": "u8|u16|u32|u64|u128|i8|i16|i32|i64|i128|bool",
"name": "entity.name.type.common.reid"
}
}
}

View File

@ -0,0 +1,232 @@
scopeName: source.reid
patterns:
- include: "#import"
- include: "#expression"
repository:
# function-definition:
# begin: "(fn)\\s*(\\w+)\\(((\\w+)\\s*\\:\\s*(\\w+),?)*\\)\\s*->\\s*(\\w+)\\s*\\{"
# end: "\\}"
# beginCaptures:
# 1:
# name: "keyword.other"
# 2:
# name: "entity.name.function"
# 4:
# name: "entity.name.parameter"
# 5:
# name: "entity.name.type"
# 6:
# name: "entity.name.type"
# patterns:
# - include: "#type"
# - include: "#expression"
import:
begin: "(import)\\s*"
end: ";"
beginCaptures:
1:
name: keyword
endCaptures:
0:
name: punctuation.semi.reid
patterns:
- include: "#identifier"
- include: "#punctiation"
punctuation:
patterns:
- match: "::"
name: keyword.operator.namespace.reid
- match: ";"
name: punctuation.semi.reid
- match: "."
name: punctuation.dot.reid
- match: ","
name: punctuation.comma.reid
expression:
patterns:
- include: "#comment"
- include: "#fn-signature"
- include: "#common-type"
- include: "#binop-impl"
- include: "#type-impl"
- include: "#struct-definition"
- include: "#block"
- include: "#binop"
- include: "#namespace"
- include: "#cast"
- include: "#function-call"
- include: "#parenthesis"
- include: "#array"
- include: "#keywords"
- include: "#struct-expression"
- include: "#number-literal"
- include: "#string-literal"
- include: "#identifier"
- include: "#punctuation"
comment:
match: "\\/\\/(.|\\/)*"
name: comment.line.double-slash.reid
fn-signature:
begin: "(fn)\\s*(\\w+)\\("
beginCaptures:
1:
name: keyword.fn.reid
2:
name: entity.name.function.reid
end: "\\)"
patterns:
- include: "#annotated-identifier"
- include: "#keywords"
- include: "#binop"
endCaptures:
2:
name: entity.name.type.reid
type-impl:
begin: >
(impl)\s*
(\w+)\s*
\{
end: "\\}"
captures:
1:
name: keyword.impl.reid
2:
name: entity.name.type
patterns:
- include: "#expression"
binop-impl:
begin: "(impl)\\s+(binop)\\s+\\(((.*)\\s*:\\s*(.*))\\)(.*)\\(((.*)\\s*:\\s*(.*))\\)\\s*->\\s*(\\w+)\\s*\\{"
end: "\\}"
beginCaptures:
1:
name: keyword.impl.reid
2:
name: keyword.impl.reid
4:
name: variable.parameter.binop.reid
5:
name: entity.name.type.parameter.binop.reid
6:
name: keyword.operator.math.reid
8:
name: variable.parameter.binop.reid
9:
name: entity.name.type.parameter.binop.reid
10:
name: entity.name.type.return.binop.reid
patterns:
- include: "#expression"
struct-definition:
begin: "(struct)\\s*(\\w+)\\s*\\{"
end: "\\}"
captures:
1:
name: keyword.struct.reid
2:
name: entity.name.type
patterns:
- include: "#annotated-identifier"
struct-expression:
begin: "([A-Z]\\w*)\\s*\\{"
end: "\\}"
captures:
1:
name: entity.name.type.struct.reid
patterns:
- include: "#expression"
number-literal:
patterns:
- match: "0x[0-9a-fA-F]+(\\.[0-9a-fA-F]+)?"
name: "constant.hexadecimal"
- match: "0o[0-7]+(\\.[0-7]+)?"
name: "constant.octal"
- match: "0b[01]+(\\.[01]+)?"
name: "constant.binary"
- match: "[0-9]+(\\.[0-9]+)?"
name: "constant.numeric"
string-literal:
begin: '"'
end: '"'
name: string.quoted.double
patterns:
- match: "\\."
name: constant.character.escape
block:
begin: "\\{"
end: "\\}"
patterns:
- include: "#expression"
namespace:
match: "(\\w+)(\\:\\:)"
captures:
1:
name: entity.name.function.reid
2:
name: keyword.operator.namespace.reid
cast:
match: "(as)\\s+(\\w+)"
captures:
1:
name: keyword.cast.reid
2:
name: entity.name.type.reid
function-call:
begin: "(\\w+)?\\("
end: "\\)"
beginCaptures:
1:
name: entity.name.function.reid
patterns:
- include: "#expression"
parenthesis:
begin: "\\("
end: "\\)"
beginCaptures:
0:
name: keyword.operator.parenthesis.reid
endCaptures:
0:
name: keyword.operator.parenthesis.reid
patterns:
- include: "#expression"
annotated-identifier:
begin: "(\\w+)\\:"
end: ","
beginCaptures:
1:
name: variable.language.reid
patterns:
- include: "#expression"
identifier:
patterns:
- match: "[A-Z]\\w*"
name: entity.name.type.reid
- match: "\\w+"
name: variable.language.reid
keywords:
patterns:
- match: "let|mut|pub|extern"
name: "storage.type.reid"
- match: "if|return"
name: "keyword.control"
- match: "self"
name: "variable.language.self.reid"
binop:
match: "\\<\\=|\\>\\=|\\=\\=|\\<|\\>|\\*|\\+|\\-|\\^|\\&\\&|\\&"
name: keyword.operator.math.reid
array:
begin: "\\["
end: "\\]"
beginCaptures:
0:
name: entity.name.type.array.reid
endCaptures:
0:
name: entity.name.type.array.reid
patterns:
- include: "#expression"
common-type:
match: "u8|u16|u32|u64|u128|i8|i16|i32|i64|i128|bool"
name: entity.name.type.common.reid

View File

@ -1,6 +1,6 @@
[package] [package]
name = "reid" name = "reid"
version = "1.0.0-beta.2" version = "1.0.0-beta.3"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -16,6 +16,6 @@ context_debug = []
[dependencies] [dependencies]
## Make it easier to generate errors ## Make it easier to generate errors
thiserror = "1.0.44" thiserror = "1.0.44"
reid-lib = { path = "../reid-llvm-lib", version = "1.0.0-beta.1", registry="gitea-teascade" } reid-lib = { path = "../reid-llvm-lib", version = "1.0.0-beta.3", registry="gitea-teascade" }
colored = {version = "3.0.0", optional = true} colored = {version = "3.0.0", optional = true}

View File

@ -228,33 +228,34 @@ impl ast::Block {
StmtKind::Let(counter_var.clone(), true, start.process(module_id)), StmtKind::Let(counter_var.clone(), true, start.process(module_id)),
counter_range.as_meta(module_id), counter_range.as_meta(module_id),
); );
let statement_range = counter_range.clone() + start.1 + end.1 + block.2;
let set_new = mir::Statement( let set_new = mir::Statement(
StmtKind::Set( StmtKind::Set(
mir::Expression( mir::Expression(
mir::ExprKind::Variable(counter_var.clone()), mir::ExprKind::Variable(counter_var.clone()),
counter_range.as_meta(module_id), (start.1 + end.1).as_meta(module_id),
), ),
mir::Expression( mir::Expression(
mir::ExprKind::BinOp( mir::ExprKind::BinOp(
mir::BinaryOperator::Add, mir::BinaryOperator::Add,
Box::new(mir::Expression( Box::new(mir::Expression(
mir::ExprKind::Variable(counter_var.clone()), mir::ExprKind::Variable(counter_var.clone()),
counter_range.as_meta(module_id), (start.1 + end.1).as_meta(module_id),
)), )),
Box::new(mir::Expression( Box::new(mir::Expression(
mir::ExprKind::Literal(mir::Literal::Vague(mir::VagueLiteral::Number(1))), mir::ExprKind::Literal(mir::Literal::Vague(mir::VagueLiteral::Number(1))),
counter_range.as_meta(module_id), (start.1 + end.1).as_meta(module_id),
)), )),
mir::TypeKind::Vague(mir::VagueType::Unknown), mir::TypeKind::Vague(mir::VagueType::Unknown),
), ),
counter_range.as_meta(module_id), (start.1 + end.1).as_meta(module_id),
), ),
), ),
counter_range.as_meta(module_id), (start.1 + end.1).as_meta(module_id),
); );
let mut block = block.into_mir(module_id); let mut mir_block = block.into_mir(module_id);
block.statements.push(set_new); mir_block.statements.push(set_new);
let while_statement = mir::Statement( let while_statement = mir::Statement(
StmtKind::While(WhileStatement { StmtKind::While(WhileStatement {
condition: mir::Expression( condition: mir::Expression(
@ -262,28 +263,28 @@ impl ast::Block {
mir::BinaryOperator::Cmp(mir::CmpOperator::LT), mir::BinaryOperator::Cmp(mir::CmpOperator::LT),
Box::new(mir::Expression( Box::new(mir::Expression(
mir::ExprKind::Variable(counter_var), mir::ExprKind::Variable(counter_var),
counter_range.as_meta(module_id), (start.1 + end.1).as_meta(module_id),
)), )),
Box::new(end.process(module_id)), Box::new(end.process(module_id)),
mir::TypeKind::Vague(mir::VagueType::Unknown), mir::TypeKind::Vague(mir::VagueType::Unknown),
), ),
counter_range.as_meta(module_id), (start.1 + end.1).as_meta(module_id),
), ),
block, block: mir_block.clone(),
meta: self.2.as_meta(module_id), meta: (start.1 + end.1 + block.2).as_meta(module_id),
}), }),
self.2.as_meta(module_id), (start.1 + end.1 + block.2).as_meta(module_id),
); );
let inner_scope = StmtKind::Expression(mir::Expression( let inner_scope = StmtKind::Expression(mir::Expression(
mir::ExprKind::Block(mir::Block { mir::ExprKind::Block(mir::Block {
statements: vec![let_statement, while_statement], statements: vec![let_statement, while_statement],
return_expression: None, return_expression: None,
meta: counter_range.as_meta(module_id) + end.1.as_meta(module_id), meta: statement_range.as_meta(module_id),
}), }),
counter_range.as_meta(module_id) + end.1.as_meta(module_id), statement_range.as_meta(module_id),
)); ));
(inner_scope, self.2) (inner_scope, statement_range)
} }
ast::BlockLevelStatement::WhileLoop(expression, block) => ( ast::BlockLevelStatement::WhileLoop(expression, block) => (
StmtKind::While(WhileStatement { StmtKind::While(WhileStatement {
@ -291,7 +292,7 @@ impl ast::Block {
block: block.into_mir(module_id), block: block.into_mir(module_id),
meta: self.2.as_meta(module_id), meta: self.2.as_meta(module_id),
}), }),
self.2, expression.1 + block.2,
), ),
}; };

View File

@ -74,7 +74,7 @@ pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDef
}], }],
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicConst(*len))), kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicConst(*len))),
source: None, source: None,
}) });
} }
_ => {} _ => {}
} }
@ -247,26 +247,17 @@ pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
scope.block.build(Instr::XOr(lhs, rhs)).unwrap() scope.block.build(Instr::XOr(lhs, rhs)).unwrap()
})); }));
if ty.signed() { if ty.signed() {
intrinsics.push(complex_binop_def( intrinsics.push(complex_binop_def(BitshiftRight, &ty, &ty, |scope, lhs, rhs| {
BitshiftRight, scope.block.build(Instr::ShiftRightArithmetic(lhs, rhs)).unwrap()
&ty, }));
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftRightArithmetic(lhs, rhs)).unwrap(),
));
} else { } else {
intrinsics.push(complex_binop_def( intrinsics.push(complex_binop_def(BitshiftRight, &ty, &ty, |scope, lhs, rhs| {
BitshiftRight, scope.block.build(Instr::ShiftRightLogical(lhs, rhs)).unwrap()
&ty, }));
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftRightLogical(lhs, rhs)).unwrap(),
));
} }
intrinsics.push(complex_binop_def( intrinsics.push(complex_binop_def(BitshiftLeft, &ty, &ty, |scope, lhs, rhs| {
BitshiftLeft, scope.block.build(Instr::ShiftLeft(lhs, rhs)).unwrap()
&ty, }));
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftLeft(lhs, rhs)).unwrap(),
));
} }
for ty in INTEGERS.iter().chain(&[TypeKind::Bool, TypeKind::Char]) { for ty in INTEGERS.iter().chain(&[TypeKind::Bool, TypeKind::Char]) {
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::EQ), &ty, |scope, lhs, rhs| { intrinsics.push(boolean_binop_def(Cmp(CmpOperator::EQ), &ty, |scope, lhs, rhs| {
@ -386,7 +377,9 @@ impl IntrinsicFunction for IntrinsicSizeOf {
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> { fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> {
let instr = scope let instr = scope
.block .block
.build(Instr::Constant(reid_lib::ConstValueKind::U64(self.0.size_of() / 8))) .build(Instr::Constant(reid_lib::ConstValueKind::U64(
self.0.size_of(&scope.type_map) / 8,
)))
.unwrap(); .unwrap();
Ok(StackValue(StackValueKind::Literal(instr), self.0.clone())) Ok(StackValue(StackValueKind::Literal(instr), self.0.clone()))
} }
@ -404,7 +397,9 @@ impl IntrinsicFunction for IntrinsicMalloc {
let sizeof = scope let sizeof = scope
.block .block
.build(Instr::Constant(ConstValueKind::U64(self.0.size_of() / 8))) .build(Instr::Constant(ConstValueKind::U64(
self.0.size_of(&scope.type_map) / 8,
)))
.unwrap(); .unwrap();
let bytes = scope.block.build(Instr::Mul(sizeof, amount.instr())).unwrap(); let bytes = scope.block.build(Instr::Mul(sizeof, amount.instr())).unwrap();
let instr = scope.block.build(Instr::FunctionCall(function, vec![bytes])).unwrap(); let instr = scope.block.build(Instr::FunctionCall(function, vec![bytes])).unwrap();

View File

@ -144,6 +144,7 @@ impl mir::Module {
let mut types = HashMap::new(); let mut types = HashMap::new();
let mut type_values = HashMap::new(); let mut type_values = HashMap::new();
let mut debug_types = HashMap::new(); let mut debug_types = HashMap::new();
let mut type_map = HashMap::new();
macro_rules! insert_debug { macro_rules! insert_debug {
($kind:expr) => { ($kind:expr) => {
@ -153,8 +154,7 @@ impl mir::Module {
&compile_unit, &compile_unit,
&debug, &debug,
&debug_types, &debug_types,
&type_values, &type_map,
&types,
self.module_id, self.module_id,
&self.tokens, &self.tokens,
&modules, &modules,
@ -182,6 +182,8 @@ impl mir::Module {
for typedef in typedefs { for typedef in typedefs {
let type_key = CustomTypeKey(typedef.name.clone(), typedef.source_module); let type_key = CustomTypeKey(typedef.name.clone(), typedef.source_module);
type_map.insert(type_key.clone(), typedef.clone());
let type_value = match &typedef.kind { let type_value = match &typedef.kind {
TypeDefinitionKind::Struct(StructType(fields)) => { TypeDefinitionKind::Struct(StructType(fields)) => {
module.custom_type(CustomTypeKind::NamedStruct(NamedStruct( module.custom_type(CustomTypeKind::NamedStruct(NamedStruct(
@ -198,6 +200,7 @@ impl mir::Module {
}; };
types.insert(type_value, typedef.clone()); types.insert(type_value, typedef.clone());
type_values.insert(type_key.clone(), type_value); type_values.insert(type_key.clone(), type_value);
insert_debug!(&TypeKind::CustomType(type_key.clone())); insert_debug!(&TypeKind::CustomType(type_key.clone()));
} }
@ -380,6 +383,7 @@ impl mir::Module {
functions: &functions, functions: &functions,
types: &types, types: &types,
type_values: &type_values, type_values: &type_values,
type_map: &type_map,
globals: &globals, globals: &globals,
stack_values: HashMap::new(), stack_values: HashMap::new(),
debug: Some(Debug { debug: Some(Debug {
@ -457,6 +461,7 @@ impl mir::Module {
functions: &functions, functions: &functions,
types: &types, types: &types,
type_values: &type_values, type_values: &type_values,
type_map: &type_map,
stack_values: HashMap::new(), stack_values: HashMap::new(),
debug: Some(Debug { debug: Some(Debug {
info: &debug, info: &debug,
@ -518,6 +523,7 @@ impl mir::Module {
functions: &functions, functions: &functions,
types: &types, types: &types,
type_values: &type_values, type_values: &type_values,
type_map: &type_map,
stack_values: HashMap::new(), stack_values: HashMap::new(),
debug: Some(Debug { debug: Some(Debug {
info: &debug, info: &debug,
@ -1311,45 +1317,47 @@ impl mir::Expression {
if val.1 == *type_kind { if val.1 == *type_kind {
Some(val) Some(val)
} else { } else {
match (&val.1, type_kind) { let (ty, other) = if !state.should_load {
(TypeKind::CodegenPtr(inner), TypeKind::UserPtr(ty2)) => match *inner.clone() { let TypeKind::CodegenPtr(inner) = &val.1 else {
TypeKind::UserPtr(_) => Some(StackValue( panic!();
val.0.derive( };
scope (*inner.clone(), TypeKind::CodegenPtr(Box::new(type_kind.clone())))
.block } else {
.build(Instr::BitCast( (val.1.clone(), type_kind.clone())
val.instr(), };
Type::Ptr(Box::new(type_kind.get_type(scope.type_values))),
)) dbg!(&ty, type_kind);
.unwrap(),
), match (&ty, type_kind) {
TypeKind::CodegenPtr(Box::new(type_kind.clone())), (TypeKind::UserPtr(_), TypeKind::UserPtr(_)) => Some(StackValue(
)), val.0.derive(
TypeKind::Borrow(ty1, _) => match *ty1.clone() { scope
TypeKind::Array(ty1, _) => { .block
if ty1 == *ty2 { .build(Instr::BitCast(val.instr(), other.get_type(scope.type_values)))
Some(StackValue( .unwrap(),
val.0.derive( ),
scope other.clone(),
.block )),
.build(Instr::BitCast( (TypeKind::Borrow(ty1, _), TypeKind::UserPtr(ty2)) => {
val.instr(), if let TypeKind::Array(ty1, _) = ty1.as_ref() {
Type::Ptr(Box::new(type_kind.get_type(scope.type_values))), if ty1 == ty2 {
)) Some(StackValue(
.unwrap(), val.0.derive(
), scope
TypeKind::CodegenPtr(Box::new(type_kind.clone())), .block
)) .build(Instr::BitCast(val.instr(), other.get_type(scope.type_values)))
} else { .unwrap(),
return Err(ErrorKind::Null); ),
} other,
))
} else {
return Err(ErrorKind::Null).unwrap();
} }
_ => return Err(ErrorKind::Null), } else {
}, return Err(ErrorKind::Null).unwrap();
_ => panic!(), }
}, }
(TypeKind::UserPtr(_), TypeKind::UserPtr(_)) (TypeKind::Char, TypeKind::U8)
| (TypeKind::Char, TypeKind::U8)
| (TypeKind::U8, TypeKind::Char) | (TypeKind::U8, TypeKind::Char)
| (TypeKind::U8, TypeKind::I8) => Some(StackValue( | (TypeKind::U8, TypeKind::I8) => Some(StackValue(
val.0.derive( val.0.derive(
@ -1361,8 +1369,7 @@ impl mir::Expression {
type_kind.clone(), type_kind.clone(),
)), )),
_ => { _ => {
let cast_instr = val let cast_instr = ty
.1
.get_type(scope.type_values) .get_type(scope.type_values)
.cast_instruction(val.instr(), &type_kind.get_type(scope.type_values)) .cast_instruction(val.instr(), &type_kind.get_type(scope.type_values))
.unwrap(); .unwrap();
@ -1378,11 +1385,30 @@ impl mir::Expression {
mir::ExprKind::AssociatedFunctionCall(ty, call) => codegen_function_call(Some(ty), call, scope, state)?, mir::ExprKind::AssociatedFunctionCall(ty, call) => codegen_function_call(Some(ty), call, scope, state)?,
mir::ExprKind::GlobalRef(global_name, ty) => { mir::ExprKind::GlobalRef(global_name, ty) => {
let global_value = scope.globals.get(global_name).unwrap(); let global_value = scope.globals.get(global_name).unwrap();
let a = Some(StackValue(
StackValueKind::Literal(scope.block.build(Instr::GetGlobal(global_value.clone())).unwrap()), let value = scope.block.build(Instr::GetGlobal(global_value.clone())).unwrap();
ty.clone(),
)); if !state.should_load {
a let allocated = scope
.block
.build(Instr::Alloca(ty.get_type(scope.type_values)))
.unwrap();
scope
.block
.build(Instr::Store(allocated, value))
.unwrap()
.maybe_location(&mut scope.block, location.clone());
let a = Some(StackValue(
StackValueKind::Literal(allocated),
TypeKind::CodegenPtr(Box::new(ty.clone())),
));
a
} else {
let a = Some(StackValue(StackValueKind::Literal(value), ty.clone()));
a
}
} }
}; };
if let Some(value) = &value { if let Some(value) = &value {

View File

@ -26,6 +26,7 @@ pub struct Scope<'ctx, 'scope> {
pub(super) block: Block<'ctx>, pub(super) block: Block<'ctx>,
pub(super) types: &'scope HashMap<TypeValue, TypeDefinition>, pub(super) types: &'scope HashMap<TypeValue, TypeDefinition>,
pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>, pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>,
pub(super) type_map: &'scope HashMap<CustomTypeKey, TypeDefinition>,
pub(super) assoc_functions: &'scope HashMap<AssociatedFunctionKey, ScopeFunctionKind<'ctx>>, pub(super) assoc_functions: &'scope HashMap<AssociatedFunctionKey, ScopeFunctionKind<'ctx>>,
pub(super) functions: &'scope HashMap<String, ScopeFunctionKind<'ctx>>, pub(super) functions: &'scope HashMap<String, ScopeFunctionKind<'ctx>>,
pub(super) binops: &'scope HashMap<BinopKey, StackBinopDefinition<'ctx>>, pub(super) binops: &'scope HashMap<BinopKey, StackBinopDefinition<'ctx>>,
@ -49,6 +50,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
functions: self.functions, functions: self.functions,
types: self.types, types: self.types,
type_values: self.type_values, type_values: self.type_values,
type_map: self.type_map,
stack_values: self.stack_values.clone(), stack_values: self.stack_values.clone(),
debug: self.debug.clone(), debug: self.debug.clone(),
allocator: self.allocator.clone(), allocator: self.allocator.clone(),

View File

@ -109,8 +109,7 @@ impl TypeKind {
&debug.scope, &debug.scope,
debug.info, debug.info,
debug.types, debug.types,
scope.type_values, scope.type_map,
scope.types,
scope.module_id, scope.module_id,
scope.tokens, scope.tokens,
scope.modules, scope.modules,
@ -122,8 +121,7 @@ impl TypeKind {
scope: &DebugScopeValue, scope: &DebugScopeValue,
debug_info: &DebugInformation, debug_info: &DebugInformation,
debug_types: &HashMap<TypeKind, DebugTypeValue>, debug_types: &HashMap<TypeKind, DebugTypeValue>,
type_values: &HashMap<CustomTypeKey, TypeValue>, type_map: &HashMap<CustomTypeKey, TypeDefinition>,
types: &HashMap<TypeValue, TypeDefinition>,
local_mod: SourceModuleId, local_mod: SourceModuleId,
tokens: &Vec<FullToken>, tokens: &Vec<FullToken>,
modules: &HashMap<SourceModuleId, ModuleCodegen>, modules: &HashMap<SourceModuleId, ModuleCodegen>,
@ -142,13 +140,12 @@ impl TypeKind {
scope, scope,
debug_info, debug_info,
debug_types, debug_types,
type_values, type_map,
types,
local_mod, local_mod,
tokens, tokens,
modules, modules,
), ),
size_bits: self.size_of(), size_bits: self.size_of(type_map),
}) })
} }
TypeKind::Array(elem_ty, len) => { TypeKind::Array(elem_ty, len) => {
@ -156,21 +153,20 @@ impl TypeKind {
scope, scope,
debug_info, debug_info,
debug_types, debug_types,
type_values, type_map,
types,
local_mod, local_mod,
tokens, tokens,
modules, modules,
); );
DebugTypeData::Array(DebugArrayType { DebugTypeData::Array(DebugArrayType {
size_bits: self.size_of(), size_bits: self.size_of(type_map),
align_bits: self.alignment(), align_bits: self.alignment(),
element_type: elem_ty, element_type: elem_ty,
length: *len, length: *len,
}) })
} }
TypeKind::CustomType(key) => { TypeKind::CustomType(key) => {
let typedef = types.get(type_values.get(key).unwrap()).unwrap(); let typedef = type_map.get(key).unwrap();
match &typedef.kind { match &typedef.kind {
TypeDefinitionKind::Struct(struct_type) => { TypeDefinitionKind::Struct(struct_type) => {
let mut fields = Vec::new(); let mut fields = Vec::new();
@ -186,21 +182,20 @@ impl TypeKind {
name: field.0.clone(), name: field.0.clone(),
scope: scope.clone(), scope: scope.clone(),
pos: location.map(|l| l.pos), pos: location.map(|l| l.pos),
size_bits: field.1.size_of(), size_bits: field.1.size_of(type_map),
offset: size_bits, offset: size_bits,
flags: DwarfFlags, flags: DwarfFlags,
ty: field.1.get_debug_type_hard( ty: field.1.get_debug_type_hard(
scope, scope,
debug_info, debug_info,
debug_types, debug_types,
type_values, type_map,
types,
local_mod, local_mod,
tokens, tokens,
modules, modules,
), ),
}); });
size_bits += field.1.size_of(); size_bits += field.1.size_of(type_map);
} }
{ {
let location = if typedef.source_module != local_mod { let location = if typedef.source_module != local_mod {
@ -222,7 +217,7 @@ impl TypeKind {
} }
_ => DebugTypeData::Basic(DebugBasicType { _ => DebugTypeData::Basic(DebugBasicType {
name, name,
size_bits: self.size_of(), size_bits: self.size_of(type_map),
encoding: match self { encoding: match self {
TypeKind::Bool => DwarfEncoding::Boolean, TypeKind::Bool => DwarfEncoding::Boolean,
TypeKind::I8 => DwarfEncoding::SignedChar, TypeKind::I8 => DwarfEncoding::SignedChar,

View File

@ -1,3 +1,5 @@
use reid_lib::builder::TypeValue;
use crate::util::maybe; use crate::util::maybe;
use super::{typecheck::typerefs::TypeRefs, *}; use super::{typecheck::typerefs::TypeRefs, *};
@ -57,7 +59,7 @@ impl TypeKind {
} }
} }
pub fn size_of(&self) -> u64 { pub fn size_of(&self, map: &HashMap<CustomTypeKey, TypeDefinition>) -> u64 {
match self { match self {
TypeKind::Bool => 1, TypeKind::Bool => 1,
TypeKind::I8 => 8, TypeKind::I8 => 8,
@ -72,8 +74,16 @@ impl TypeKind {
TypeKind::U128 => 128, TypeKind::U128 => 128,
TypeKind::Void => 0, TypeKind::Void => 0,
TypeKind::Char => 8, TypeKind::Char => 8,
TypeKind::Array(type_kind, len) => type_kind.size_of() * (*len as u64), TypeKind::Array(type_kind, len) => type_kind.size_of(map) * (*len as u64),
TypeKind::CustomType(..) => 32, TypeKind::CustomType(key) => match &map.get(key).unwrap().kind {
TypeDefinitionKind::Struct(struct_type) => {
let mut size = 0;
for field in &struct_type.0 {
size += field.1.size_of(map)
}
size
}
},
TypeKind::CodegenPtr(_) => 64, TypeKind::CodegenPtr(_) => 64,
TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"), TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"),
TypeKind::Borrow(..) => 64, TypeKind::Borrow(..) => 64,

View File

@ -118,10 +118,13 @@ impl mir::Expression {
let mut globals = Vec::new(); let mut globals = Vec::new();
match &mut self.0 { match &mut self.0 {
mir::ExprKind::FunctionCall(function_call) => { mir::ExprKind::FunctionCall(function_call) => {
for param in &mut function_call.parameters {
globals.extend(param.gen_macros(data, state, map));
}
if function_call.is_macro { if function_call.is_macro {
if let Some(existing_macro) = data.macros.get(&function_call.name) { if let Some(existing_macro) = data.macros.get(&function_call.name) {
let mut literals = Vec::new(); let mut literals = Vec::new();
for param in &function_call.parameters { for param in &mut function_call.parameters {
match &param.0 { match &param.0 {
super::ExprKind::Literal(literal) => literals.push(literal.clone()), super::ExprKind::Literal(literal) => literals.push(literal.clone()),
_ => state.note_errors(&vec![ErrorKind::InvalidMacroArgs], param.1), _ => state.note_errors(&vec![ErrorKind::InvalidMacroArgs], param.1),

View File

@ -6,12 +6,12 @@ use reid::{
mir::{self}, mir::{self},
parse_module, perform_all_passes, parse_module, perform_all_passes,
}; };
use reid_lib::Context; use reid_lib::{compile::CompileOutput, Context};
use util::assert_err; use util::assert_err;
mod util; mod util;
fn test(source: &str, name: &str, expected_exit_code: Option<i32>) { fn test_compile(source: &str, name: &str) -> CompileOutput {
assert_err(assert_err(std::panic::catch_unwind(|| { assert_err(assert_err(std::panic::catch_unwind(|| {
let mut map = Default::default(); let mut map = Default::default();
let (id, tokens) = assert_err(parse_module(source, name, &mut map)); let (id, tokens) = assert_err(parse_module(source, name, &mut map));
@ -24,7 +24,14 @@ fn test(source: &str, name: &str, expected_exit_code: Option<i32>) {
let codegen = assert_err(mir_context.codegen(&context)); let codegen = assert_err(mir_context.codegen(&context));
let output = codegen.compile(None, Vec::new()).output(); Ok::<_, ()>(codegen.compile(None, Vec::new()).output())
})))
}
fn test(source: &str, name: &str, expected_exit_code: Option<i32>) {
assert_err(assert_err(std::panic::catch_unwind(|| {
let output = test_compile(source, name);
let time = SystemTime::now(); let time = SystemTime::now();
let in_path = PathBuf::from(format!( let in_path = PathBuf::from(format!(
"/tmp/temp-{}.o", "/tmp/temp-{}.o",
@ -157,3 +164,8 @@ fn associated_functions() {
fn mutable_inner_functions() { fn mutable_inner_functions() {
test(include_str!("../../examples/mutable_inner.reid"), "test", Some(0)); test(include_str!("../../examples/mutable_inner.reid"), "test", Some(0));
} }
#[test]
fn cpu_raytracer_compiles() {
test_compile(include_str!("../../examples/cpu_raytracer.reid"), "test");
}