summaryrefslogtreecommitdiff
path: root/oryxc/src
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2026-03-30 22:53:28 +0200
committerThomas Voss <mail@thomasvoss.com> 2026-03-30 22:53:28 +0200
commitbc548238b9dd1d15ddf0af8731d356a0ca6a61ad (patch)
treefce34d062211d1af1aa867253fae72bf26340ea5 /oryxc/src
parent82ce31a7be9a67ea88c586c2792a7dcddd2a53d6 (diff)
Expand UnaryOperator and BinaryOperator
Diffstat (limited to 'oryxc/src')
-rw-r--r--oryxc/src/parser.rs195
-rw-r--r--oryxc/src/sema/typecheck.rs63
2 files changed, 215 insertions, 43 deletions
diff --git a/oryxc/src/parser.rs b/oryxc/src/parser.rs
index 93adc9f..cd398fd 100644
--- a/oryxc/src/parser.rs
+++ b/oryxc/src/parser.rs
@@ -15,38 +15,107 @@ use crate::size;
const MAX_PREC: i64 = 6;
-/* Remember to edit the cases in Parser.node_leaf_*() when editing
- * this list! */
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum AstType {
- Assign, /* (extra-data-lhs, extra-data-rhs) */
- BinaryOperator, /* (lhs, rhs) */
- Block, /* (extra-data, extra-data-len) */
- Dereference, /* (lhs, _) */
- Empty, /* (_, _) */
- FunCall, /* (expression, extra-data-exprs) */
- FunProto, /* (extra-data-args, extra-data-rets) */
- Function, /* (prototype, body) */
- Identifier, /* (_, _) */
- MultiDefBind, /* (extra-data-decls, extra-data-exprs) */
- Number, /* (_, _) */
- Pointer, /* (rhs, _) */
- Return, /* (extra-data, extra-data-len) */
- Root, /* (extra-data, extra-data-len) */
- String, /* (_, _) */
- UnaryOperator, /* (rhs, _) */
+ AddressOf, /* (rhs, _) */
+ Assign, /* (extra-data-lhs, extra-data-rhs) */
+ BinaryAdd, /* (lhs, rhs) */
+ BinaryBitAnd, /* (lhs, rhs) */
+ BinaryBitAndNot, /* (lhs, rhs) */
+ BinaryBitOr, /* (lhs, rhs) */
+ BinaryBitXor, /* (lhs, rhs) */
+ BinaryDivRem, /* (lhs, rhs) */
+ BinaryDivide, /* (lhs, rhs) */
+ BinaryEqual, /* (lhs, rhs) */
+ BinaryGreaterThan, /* (lhs, rhs) */
+ BinaryGreaterThanEqual, /* (lhs, rhs) */
+ BinaryLeftRotate, /* (lhs, rhs) */
+ BinaryLeftShift, /* (lhs, rhs) */
+ BinaryLessThan, /* (lhs, rhs) */
+ BinaryLessThanEqual, /* (lhs, rhs) */
+ BinaryLogicalAnd, /* (lhs, rhs) */
+ BinaryLogicalOr, /* (lhs, rhs) */
+ BinaryModulus, /* (lhs, rhs) */
+ BinaryMultiply, /* (lhs, rhs) */
+ BinaryNotEqual, /* (lhs, rhs) */
+ BinaryRemainder, /* (lhs, rhs) */
+ BinaryRightRotate, /* (lhs, rhs) */
+ BinaryRightShift, /* (lhs, rhs) */
+ BinarySubtract, /* (lhs, rhs) */
+ Block, /* (extra-data, extra-data-len) */
+ Dereference, /* (lhs, _) */
+ Empty, /* (_, _) */
+ FunCall, /* (expression, extra-data-exprs) */
+ FunProto, /* (extra-data-args, extra-data-rets) */
+ Function, /* (prototype, body) */
+ Identifier, /* (_, _) */
+ MultiDefBind, /* (extra-data-decls, extra-data-exprs) */
+ Number, /* (_, _) */
+ Pointer, /* (rhs, _) */
+ Return, /* (extra-data, extra-data-len) */
+ Root, /* (extra-data, extra-data-len) */
+ String, /* (_, _) */
+ UnaryComplement, /* (rhs, _) */
+ UnaryMinus, /* (rhs, _) */
+ UnaryNegate, /* (rhs, _) */
+ UnaryPlus, /* (rhs, _) */
}
-/// The number of AstType variants that represent expressions/binops/etc. In
-/// the places where we match/switch on just the subset of AstTypes that are
-/// expressions/etc., we can static assert that this equals its current value.
-/// This is useful because if a new AstType of the given subset is added and
-/// these numbers are incremented, the static asserts fail everywhere where code
-/// changes are required.
-pub const NEXPRKINDS: usize = 10;
-pub const NUNARYKINDS: usize = 5;
+impl AstType {
+ pub fn unary_prefix_from(t: TokenType) -> Self {
+ const { assert!(NUNARYKINDS == 7, "missing mapping") };
+ return match t {
+ TokenType::Ampersand => Self::AddressOf,
+ TokenType::Bang => Self::UnaryNegate,
+ TokenType::Caret => Self::Pointer,
+ TokenType::Minus => Self::UnaryMinus,
+ TokenType::Plus => Self::UnaryPlus,
+ TokenType::Tilde => Self::UnaryComplement,
+ _ => unreachable!(),
+ };
+ }
+
+ pub fn binary_from(t: TokenType) -> Self {
+ const { assert!(NBINARYKINDS == 23, "missing mapping") };
+ return match t {
+ TokenType::Ampersand => Self::BinaryBitAnd,
+ TokenType::Ampersand2 => Self::BinaryLogicalAnd,
+ TokenType::AmpersandTilde => Self::BinaryBitAndNot,
+ TokenType::AngleL => Self::BinaryLessThan,
+ TokenType::AngleL2 => Self::BinaryLeftShift,
+ TokenType::AngleL3 => Self::BinaryLeftRotate,
+ TokenType::AngleLEquals => Self::BinaryLessThanEqual,
+ TokenType::AngleR => Self::BinaryGreaterThan,
+ TokenType::AngleR2 => Self::BinaryRightShift,
+ TokenType::AngleR3 => Self::BinaryRightRotate,
+ TokenType::AngleREquals => Self::BinaryGreaterThanEqual,
+ TokenType::Asterisk => Self::BinaryMultiply,
+ TokenType::BangEquals => Self::BinaryNotEqual,
+ TokenType::Bar => Self::BinaryBitOr,
+ TokenType::Bar2 => Self::BinaryLogicalOr,
+ TokenType::Equals2 => Self::BinaryEqual,
+ TokenType::Minus => Self::BinarySubtract,
+ TokenType::Percent => Self::BinaryRemainder,
+ TokenType::Percent2 => Self::BinaryModulus,
+ TokenType::Plus => Self::BinaryAdd,
+ TokenType::Slash => Self::BinaryDivide,
+ TokenType::SlashPercent => Self::BinaryDivRem,
+ TokenType::Tilde => Self::BinaryBitXor,
+ _ => unreachable!(),
+ };
+ }
+}
+
+/// The number of AstType variants that represent expressions/binops/etc.
+/// In the places where we match/switch on just the subset of AstTypes
+/// that are expressions/etc., we can static assert that this equals its
+/// current value. This is useful because if a new AstType of the given
+/// subset is added and these numbers are incremented, the static asserts
+/// fail everywhere where code changes are required.
+pub const NUNARYKINDS: usize = 7;
pub const NBINARYKINDS: usize = 23;
+pub const NEXPRKINDS: usize = NUNARYKINDS + NBINARYKINDS + 6;
#[derive(Soars)]
#[soa_derive(Debug)]
@@ -162,7 +231,29 @@ impl<'a> Parser<'a> {
let expr = self.extra_data[i as usize];
self.node_leaf_l(expr)
},
- AstType::BinaryOperator => {
+ AstType::BinaryAdd
+ | AstType::BinaryBitAnd
+ | AstType::BinaryBitAndNot
+ | AstType::BinaryBitOr
+ | AstType::BinaryBitXor
+ | AstType::BinaryDivRem
+ | AstType::BinaryDivide
+ | AstType::BinaryEqual
+ | AstType::BinaryGreaterThan
+ | AstType::BinaryGreaterThanEqual
+ | AstType::BinaryLeftRotate
+ | AstType::BinaryLeftShift
+ | AstType::BinaryLessThan
+ | AstType::BinaryLessThanEqual
+ | AstType::BinaryLogicalAnd
+ | AstType::BinaryLogicalOr
+ | AstType::BinaryModulus
+ | AstType::BinaryMultiply
+ | AstType::BinaryNotEqual
+ | AstType::BinaryRemainder
+ | AstType::BinaryRightRotate
+ | AstType::BinaryRightShift
+ | AstType::BinarySubtract => {
self.node_leaf_l(self.ast.sub()[node as usize].0)
},
AstType::Block => {
@@ -196,7 +287,12 @@ impl<'a> Parser<'a> {
}
},
AstType::String => node,
- AstType::UnaryOperator => node,
+ AstType::AddressOf
+ | AstType::Pointer
+ | AstType::UnaryComplement
+ | AstType::UnaryMinus
+ | AstType::UnaryNegate
+ | AstType::UnaryPlus => node,
};
}
@@ -207,7 +303,29 @@ impl<'a> Parser<'a> {
let nexprs = self.extra_data[i as usize];
self.node_leaf_r(self.extra_data[(i + nexprs) as usize])
},
- AstType::BinaryOperator => {
+ AstType::BinaryAdd
+ | AstType::BinaryBitAnd
+ | AstType::BinaryBitAndNot
+ | AstType::BinaryBitOr
+ | AstType::BinaryBitXor
+ | AstType::BinaryDivRem
+ | AstType::BinaryDivide
+ | AstType::BinaryEqual
+ | AstType::BinaryGreaterThan
+ | AstType::BinaryGreaterThanEqual
+ | AstType::BinaryLeftRotate
+ | AstType::BinaryLeftShift
+ | AstType::BinaryLessThan
+ | AstType::BinaryLessThanEqual
+ | AstType::BinaryLogicalAnd
+ | AstType::BinaryLogicalOr
+ | AstType::BinaryModulus
+ | AstType::BinaryMultiply
+ | AstType::BinaryNotEqual
+ | AstType::BinaryRemainder
+ | AstType::BinaryRightRotate
+ | AstType::BinaryRightShift
+ | AstType::BinarySubtract => {
self.node_leaf_r(self.ast.sub()[node as usize].1)
},
AstType::Block => {
@@ -273,9 +391,12 @@ impl<'a> Parser<'a> {
}
},
AstType::String => node,
- AstType::UnaryOperator => {
- self.node_leaf_r(self.ast.sub()[node as usize].0)
- },
+ AstType::AddressOf
+ | AstType::Pointer
+ | AstType::UnaryComplement
+ | AstType::UnaryMinus
+ | AstType::UnaryNegate
+ | AstType::UnaryPlus => self.node_leaf_r(self.ast.sub()[node as usize].0),
};
}
@@ -763,13 +884,13 @@ impl<'a> Parser<'a> {
| TokenType::Minus
| TokenType::Plus
| TokenType::Tilde => {
- let i = self.cursor;
+ let tok = self.cursor;
self.next();
let rhs = self.parse_expr(MAX_PREC)?;
self.new_node(AstNode {
- kind: AstType::UnaryOperator,
- tok: i,
- sub: SubNodes(rhs, u32::MAX),
+ kind: AstType::unary_prefix_from(self.get_at(tok)),
+ tok,
+ sub: SubNodes(rhs, u32::MAX),
})
},
TokenType::ParenL => {
@@ -853,7 +974,7 @@ impl<'a> Parser<'a> {
self.next();
let rhs = self.parse_expr(prec)?;
self.new_node(AstNode {
- kind: AstType::BinaryOperator,
+ kind: AstType::binary_from(tok),
tok: i,
sub: SubNodes(lhs, rhs),
})
diff --git a/oryxc/src/sema/typecheck.rs b/oryxc/src/sema/typecheck.rs
index 27c3e31..5cb37c7 100644
--- a/oryxc/src/sema/typecheck.rs
+++ b/oryxc/src/sema/typecheck.rs
@@ -137,11 +137,9 @@ fn typecheck_expr(
let ast = fdata.ast.get().unwrap();
let tokens = fdata.tokens.get().unwrap();
- const {
- assert!(parser::NEXPRKINDS == 10, "Missing expression case");
- };
+ const { assert!(parser::NEXPRKINDS == 36, "missing expression case") };
+
let expr_type = match ast.nodes.kind()[node as usize] {
- AstType::BinaryOperator => todo!(),
AstType::Dereference => {
let pointer = ast.nodes.sub()[node as usize].0;
let ptype = typecheck_expr(c_state, fdata, pointer)?;
@@ -165,8 +163,61 @@ fn typecheck_expr(
let base = typecheck_expr(c_state, fdata, pointee)?;
c_state.type_intr.intern(OryxType::Pointer { base })
},
- AstType::String => todo!(),
- AstType::UnaryOperator => todo!(),
+ AstType::String => c_state.type_intr.intern(OryxType::UString),
+
+ /* Unary ops */
+ AstType::AddressOf => todo!(),
+ AstType::Pointer => todo!(),
+ AstType::UnaryComplement
+ | AstType::UnaryMinus
+ | AstType::UnaryNegate
+ | AstType::UnaryPlus => {
+ let rhs = ast.nodes.sub()[node as usize].0;
+ let base = typecheck_expr(c_state, fdata, rhs)?;
+ todo!("assert that type is numeric");
+ base
+ },
+
+ /* Binary ops */
+ AstType::BinaryEqual
+ | AstType::BinaryGreaterThan
+ | AstType::BinaryGreaterThanEqual
+ | AstType::BinaryLessThan
+ | AstType::BinaryLessThanEqual
+ | AstType::BinaryLogicalOr
+ | AstType::BinaryNotEqual => {
+ let SubNodes(lhs, rhs) = ast.nodes.sub()[node as usize];
+ let ltype = typecheck_expr(c_state, fdata, lhs)?;
+ let rtype = typecheck_expr(c_state, fdata, rhs)?;
+ todo!("assert that types are boolean");
+ },
+ AstType::BinaryDivRem => {
+ let SubNodes(lhs, rhs) = ast.nodes.sub()[node as usize];
+ let ltype = typecheck_expr(c_state, fdata, lhs)?;
+ let rtype = typecheck_expr(c_state, fdata, rhs)?;
+ todo!("assert that types are numeric");
+ },
+ AstType::BinaryAdd
+ | AstType::BinaryBitAnd
+ | AstType::BinaryBitAndNot
+ | AstType::BinaryBitOr
+ | AstType::BinaryBitXor
+ | AstType::BinaryDivide
+ | AstType::BinaryLeftRotate
+ | AstType::BinaryLeftShift
+ | AstType::BinaryLogicalAnd
+ | AstType::BinaryModulus
+ | AstType::BinaryMultiply
+ | AstType::BinaryRemainder
+ | AstType::BinaryRightRotate
+ | AstType::BinaryRightShift
+ | AstType::BinarySubtract => {
+ let SubNodes(lhs, rhs) = ast.nodes.sub()[node as usize];
+ let ltype = typecheck_expr(c_state, fdata, lhs)?;
+ let rtype = typecheck_expr(c_state, fdata, rhs)?;
+ todo!("assert that types are numeric");
+ },
+
_ => unreachable!(),
};