Compare commits

..

9 Commits
lsp ... main

16 changed files with 853 additions and 146 deletions

View File

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

View File

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

View File

@ -4,5 +4,6 @@ import std::print;
fn main() -> u8 {
let bytes = include_bytes!("./macro_easy_file.txt");
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

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

View File

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

View File

@ -43,11 +43,18 @@
"description": "Traces the communication between VS Code and the language server."
}
}
}
},
"grammars": [
{
"language": "reid",
"scopeName": "source.reid",
"path": "./syntaxes/grammar.json"
}
]
},
"scripts": {
"vscode:prepublish": "pnpm run package",
"compile": "webpack",
"compile": "npx js-yaml syntaxes/grammar.yaml > syntaxes/grammar.json && webpack",
"watch": "webpack --watch",
"package": "webpack --mode production --devtool hidden-source-map",
"compile-tests": "tsc -p . --outDir out",
@ -65,6 +72,7 @@
"@vscode/test-cli": "^0.0.11",
"@vscode/test-electron": "^2.5.2",
"eslint": "^9.25.1",
"js-yaml": "^4.1.0",
"ts-loader": "^9.5.2",
"typescript": "^5.8.3",
"webpack": "^5.99.7",

View File

@ -12,9 +12,9 @@ use reid::{compile_module, parse_module, perform_all_passes};
use tower_lsp::lsp_types::{
self, CompletionItem, CompletionOptions, CompletionParams, CompletionResponse, Diagnostic, DiagnosticSeverity,
DidChangeTextDocumentParams, DidOpenTextDocumentParams, Hover, HoverContents, HoverParams, HoverProviderCapability,
InitializeParams, InitializeResult, InitializedParams, MarkedString, MessageType, OneOf, Range, ServerCapabilities,
TextDocumentItem, TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions,
WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities,
InitializeParams, InitializeResult, InitializedParams, MarkedString, MarkupContent, MarkupKind, MessageType, OneOf,
Range, ServerCapabilities, TextDocumentItem, TextDocumentSyncCapability, TextDocumentSyncKind,
TextDocumentSyncOptions, WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities,
};
use tower_lsp::{Client, LanguageServer, LspService, Server, jsonrpc};
@ -91,24 +91,38 @@ impl LanguageServer for Backend {
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) {
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() {
format!("{}", ty)
(Some(range), format!("{}", ty))
} else {
String::from("no type")
(Some(range), String::from("no type"))
}
} else {
String::from("no token")
(None, String::from("no token"))
}
} else {
String::from("no token")
(None, String::from("no token"))
};
Ok(Some(Hover {
contents: HoverContents::Scalar(MarkedString::String(format!("{}", ty))),
range: None,
}))
let contents = HoverContents::Markup(MarkupContent {
kind: MarkupKind::Markdown,
value: format!("`{ty}`"),
});
Ok(Some(Hover { contents, range }))
}
async fn did_open(&self, params: DidOpenTextDocumentParams) {
@ -272,6 +286,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 {
if !(function.signature() + function.block_meta()).contains(token_idx) {
continue;
@ -372,7 +420,7 @@ pub fn find_type_in_expr(expr: &mir::Expression, module_id: SourceModuleId, toke
Some(TypeKind::CustomType(mir::CustomTypeKey(name.clone(), module_id)))
}
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) {
return Some(ty);
}

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

@ -74,7 +74,7 @@ pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDef
}],
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicConst(*len))),
source: None,
})
});
}
_ => {}
}
@ -247,26 +247,17 @@ pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
scope.block.build(Instr::XOr(lhs, rhs)).unwrap()
}));
if ty.signed() {
intrinsics.push(complex_binop_def(
BitshiftRight,
&ty,
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftRightArithmetic(lhs, rhs)).unwrap(),
));
intrinsics.push(complex_binop_def(BitshiftRight, &ty, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::ShiftRightArithmetic(lhs, rhs)).unwrap()
}));
} else {
intrinsics.push(complex_binop_def(
BitshiftRight,
&ty,
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftRightLogical(lhs, rhs)).unwrap(),
));
intrinsics.push(complex_binop_def(BitshiftRight, &ty, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::ShiftRightLogical(lhs, rhs)).unwrap()
}));
}
intrinsics.push(complex_binop_def(
BitshiftLeft,
&ty,
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftLeft(lhs, rhs)).unwrap(),
));
intrinsics.push(complex_binop_def(BitshiftLeft, &ty, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::ShiftLeft(lhs, rhs)).unwrap()
}));
}
for ty in INTEGERS.iter().chain(&[TypeKind::Bool, TypeKind::Char]) {
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> {
let instr = scope
.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();
Ok(StackValue(StackValueKind::Literal(instr), self.0.clone()))
}
@ -404,7 +397,9 @@ impl IntrinsicFunction for IntrinsicMalloc {
let sizeof = scope
.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();
let bytes = scope.block.build(Instr::Mul(sizeof, amount.instr())).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 type_values = HashMap::new();
let mut debug_types = HashMap::new();
let mut type_map = HashMap::new();
macro_rules! insert_debug {
($kind:expr) => {
@ -153,8 +154,7 @@ impl mir::Module {
&compile_unit,
&debug,
&debug_types,
&type_values,
&types,
&type_map,
self.module_id,
&self.tokens,
&modules,
@ -182,6 +182,8 @@ impl mir::Module {
for typedef in typedefs {
let type_key = CustomTypeKey(typedef.name.clone(), typedef.source_module);
type_map.insert(type_key.clone(), typedef.clone());
let type_value = match &typedef.kind {
TypeDefinitionKind::Struct(StructType(fields)) => {
module.custom_type(CustomTypeKind::NamedStruct(NamedStruct(
@ -198,6 +200,7 @@ impl mir::Module {
};
types.insert(type_value, typedef.clone());
type_values.insert(type_key.clone(), type_value);
insert_debug!(&TypeKind::CustomType(type_key.clone()));
}
@ -380,6 +383,7 @@ impl mir::Module {
functions: &functions,
types: &types,
type_values: &type_values,
type_map: &type_map,
globals: &globals,
stack_values: HashMap::new(),
debug: Some(Debug {
@ -457,6 +461,7 @@ impl mir::Module {
functions: &functions,
types: &types,
type_values: &type_values,
type_map: &type_map,
stack_values: HashMap::new(),
debug: Some(Debug {
info: &debug,
@ -518,6 +523,7 @@ impl mir::Module {
functions: &functions,
types: &types,
type_values: &type_values,
type_map: &type_map,
stack_values: HashMap::new(),
debug: Some(Debug {
info: &debug,
@ -1311,45 +1317,47 @@ impl mir::Expression {
if val.1 == *type_kind {
Some(val)
} else {
match (&val.1, type_kind) {
(TypeKind::CodegenPtr(inner), TypeKind::UserPtr(ty2)) => match *inner.clone() {
TypeKind::UserPtr(_) => Some(StackValue(
val.0.derive(
scope
.block
.build(Instr::BitCast(
val.instr(),
Type::Ptr(Box::new(type_kind.get_type(scope.type_values))),
))
.unwrap(),
),
TypeKind::CodegenPtr(Box::new(type_kind.clone())),
)),
TypeKind::Borrow(ty1, _) => match *ty1.clone() {
TypeKind::Array(ty1, _) => {
if ty1 == *ty2 {
Some(StackValue(
val.0.derive(
scope
.block
.build(Instr::BitCast(
val.instr(),
Type::Ptr(Box::new(type_kind.get_type(scope.type_values))),
))
.unwrap(),
),
TypeKind::CodegenPtr(Box::new(type_kind.clone())),
))
} else {
return Err(ErrorKind::Null);
}
let (ty, other) = if !state.should_load {
let TypeKind::CodegenPtr(inner) = &val.1 else {
panic!();
};
(*inner.clone(), TypeKind::CodegenPtr(Box::new(type_kind.clone())))
} else {
(val.1.clone(), type_kind.clone())
};
dbg!(&ty, type_kind);
match (&ty, type_kind) {
(TypeKind::UserPtr(_), TypeKind::UserPtr(_)) => Some(StackValue(
val.0.derive(
scope
.block
.build(Instr::BitCast(val.instr(), other.get_type(scope.type_values)))
.unwrap(),
),
other.clone(),
)),
(TypeKind::Borrow(ty1, _), TypeKind::UserPtr(ty2)) => {
if let TypeKind::Array(ty1, _) = ty1.as_ref() {
if ty1 == ty2 {
Some(StackValue(
val.0.derive(
scope
.block
.build(Instr::BitCast(val.instr(), other.get_type(scope.type_values)))
.unwrap(),
),
other,
))
} else {
return Err(ErrorKind::Null).unwrap();
}
_ => return Err(ErrorKind::Null),
},
_ => panic!(),
},
(TypeKind::UserPtr(_), TypeKind::UserPtr(_))
| (TypeKind::Char, TypeKind::U8)
} else {
return Err(ErrorKind::Null).unwrap();
}
}
(TypeKind::Char, TypeKind::U8)
| (TypeKind::U8, TypeKind::Char)
| (TypeKind::U8, TypeKind::I8) => Some(StackValue(
val.0.derive(
@ -1361,8 +1369,7 @@ impl mir::Expression {
type_kind.clone(),
)),
_ => {
let cast_instr = val
.1
let cast_instr = ty
.get_type(scope.type_values)
.cast_instruction(val.instr(), &type_kind.get_type(scope.type_values))
.unwrap();
@ -1378,11 +1385,30 @@ impl mir::Expression {
mir::ExprKind::AssociatedFunctionCall(ty, call) => codegen_function_call(Some(ty), call, scope, state)?,
mir::ExprKind::GlobalRef(global_name, ty) => {
let global_value = scope.globals.get(global_name).unwrap();
let a = Some(StackValue(
StackValueKind::Literal(scope.block.build(Instr::GetGlobal(global_value.clone())).unwrap()),
ty.clone(),
));
a
let value = scope.block.build(Instr::GetGlobal(global_value.clone())).unwrap();
if !state.should_load {
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 {

View File

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

View File

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

View File

@ -1,3 +1,5 @@
use reid_lib::builder::TypeValue;
use crate::util::maybe;
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 {
TypeKind::Bool => 1,
TypeKind::I8 => 8,
@ -72,8 +74,16 @@ impl TypeKind {
TypeKind::U128 => 128,
TypeKind::Void => 0,
TypeKind::Char => 8,
TypeKind::Array(type_kind, len) => type_kind.size_of() * (*len as u64),
TypeKind::CustomType(..) => 32,
TypeKind::Array(type_kind, len) => type_kind.size_of(map) * (*len as u64),
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::Vague(_) => panic!("Tried to sizeof a vague type!"),
TypeKind::Borrow(..) => 64,

View File

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

View File

@ -6,12 +6,12 @@ use reid::{
mir::{self},
parse_module, perform_all_passes,
};
use reid_lib::Context;
use reid_lib::{compile::CompileOutput, Context};
use util::assert_err;
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(|| {
let mut map = Default::default();
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 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 in_path = PathBuf::from(format!(
"/tmp/temp-{}.o",
@ -157,3 +164,8 @@ fn associated_functions() {
fn mutable_inner_functions() {
test(include_str!("../../examples/mutable_inner.reid"), "test", Some(0));
}
#[test]
fn cpu_raytracer_compiles() {
test_compile(include_str!("../../examples/cpu_raytracer.reid"), "test");
}