use std::rc::Rc;
use std::sync::Arc;
pub type Reg = u16;
#[derive(Clone)]
pub enum Const {
Float(f64),
Char(char),
Str(Arc<str>),
Bytes(Arc<[u8]>),
}
pub const DISCARD: Reg = Reg::MAX;
#[derive(Clone, Copy, Debug)]
pub enum BinKind {
Add,
Sub,
Mul,
Div,
Rem,
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
BitAnd,
BitOr,
BitXor,
Shl,
Shr,
}
#[derive(Clone, Copy, Debug)]
pub enum UnKind {
Neg,
Not,
}
#[derive(Clone)]
pub enum Member {
Named(Rc<str>),
Indexed(usize),
}
#[derive(Clone, Copy)]
pub enum CapSource {
Local(Reg),
Upvalue(u16),
MutableLocal(Reg),
MutableUpvalue(u16),
}
impl CapSource {
pub fn is_mutable(self) -> bool {
matches!(self, Self::MutableLocal(_) | Self::MutableUpvalue(_))
}
}
pub struct StructLit {
pub shape: Rc<super::value::StructShape>,
pub has_rest: bool,
}
#[derive(Clone)]
pub struct EnumVariant {
pub enum_name: Rc<str>,
pub variant: Rc<str>,
}
#[derive(Clone)]
pub struct MethodName {
pub text: String,
pub id: BuiltinId,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum BuiltinId {
Len,
IsEmpty,
Clone,
ToString,
Get,
Insert,
ContainsKey,
Remove,
Entry,
Keys,
Values,
Iter,
IterMut,
Push,
Pop,
First,
Last,
Contains,
Sort,
Join,
Concat,
Sum,
Enumerate,
Rev,
Count,
Take,
Skip,
PushStr,
Then,
CloneFrom,
SplitWhitespace,
Split,
Chars,
Lines,
Trim,
StartsWith,
EndsWith,
Parse,
Unwrap,
UnwrapOr,
Copied,
Map,
Filter,
FilterMap,
FlatMap,
ForEach,
Find,
Position,
Any,
All,
Fold,
Reduce,
Retain,
SortByKey,
SortByCachedKey,
SortBy,
MaxByKey,
MinByKey,
TakeWhile,
SkipWhile,
Partition,
AndThen,
MapErr,
MapOr,
UnwrapOrElse,
OkOrElse,
WithContext,
OrInsertWith,
OrInsertWithKey,
AndModify,
Other,
}
impl BuiltinId {
pub fn resolve(name: &str) -> BuiltinId {
use BuiltinId::*;
match name {
"len" => Len,
"is_empty" => IsEmpty,
"clone" => Clone,
"to_string" => ToString,
"get" | "get_mut" => Get,
"then" => Then,
"clone_from" => CloneFrom,
"insert" => Insert,
"contains_key" => ContainsKey,
"remove" => Remove,
"entry" => Entry,
"keys" => Keys,
"values" => Values,
"iter" | "into_iter" => Iter,
"iter_mut" => IterMut,
"push" => Push,
"pop" => Pop,
"first" => First,
"last" => Last,
"contains" => Contains,
"sort" => Sort,
"join" => Join,
"concat" => Concat,
"sum" => Sum,
"enumerate" => Enumerate,
"rev" => Rev,
"count" => Count,
"take" => Take,
"skip" => Skip,
"push_str" => PushStr,
"split_whitespace" => SplitWhitespace,
"split" => Split,
"chars" => Chars,
"lines" => Lines,
"trim" => Trim,
"starts_with" => StartsWith,
"ends_with" => EndsWith,
"parse" => Parse,
"unwrap" => Unwrap,
"unwrap_or" => UnwrapOr,
"copied" | "cloned" => Copied,
"map" => Map,
"filter" => Filter,
"filter_map" => FilterMap,
"flat_map" => FlatMap,
"for_each" => ForEach,
"find" => Find,
"position" => Position,
"any" => Any,
"all" => All,
"fold" => Fold,
"reduce" => Reduce,
"retain" => Retain,
"sort_by_key" => SortByKey,
"sort_by_cached_key" => SortByCachedKey,
"sort_by" => SortBy,
"max_by_key" => MaxByKey,
"min_by_key" => MinByKey,
"take_while" => TakeWhile,
"skip_while" => SkipWhile,
"partition" => Partition,
"and_then" => AndThen,
"map_err" => MapErr,
"map_or" => MapOr,
"unwrap_or_else" => UnwrapOrElse,
"ok_or_else" => OkOrElse,
"with_context" => WithContext,
"or_insert_with" => OrInsertWith,
"or_insert_with_key" => OrInsertWithKey,
"and_modify" => AndModify,
_ => Other,
}
}
pub fn is_higher_order(self) -> bool {
use BuiltinId::*;
matches!(
self,
Then | Map
| Filter
| FilterMap
| FlatMap
| ForEach
| Find
| Position
| Any
| All
| Fold
| Reduce
| Retain
| SortByKey
| SortByCachedKey
| SortBy
| MaxByKey
| MinByKey
| TakeWhile
| SkipWhile
| Partition
| AndThen
| MapErr
| MapOr
| UnwrapOrElse
| OkOrElse
| WithContext
| OrInsertWith
| OrInsertWithKey
| AndModify
| Other
)
}
}
#[derive(Clone)]
pub struct FmtSpec {
pub template: String,
pub positional: Vec<Reg>,
pub named: Vec<(String, Reg)>,
}
pub struct PatInfo {
pub pat: PPat,
pub binds: Vec<(String, Reg)>,
}
#[derive(Clone)]
pub enum PLit {
Int(i64),
Float(f64),
Bool(bool),
Str(String),
Char(char),
}
#[derive(Clone)]
pub enum PPat {
Wild,
Rest,
Ident {
name: String,
sub: Option<Box<PPat>>,
},
Lit(PLit),
Tuple(Vec<PPat>),
TupleStruct {
name: Option<String>,
elems: Vec<PPat>,
},
Path {
name: Option<String>,
},
Struct {
name: Option<String>,
fields: Vec<(String, PPat)>,
},
Or(Vec<PPat>),
Slice(Vec<PPat>),
Range {
lo: Option<PLit>,
hi: Option<PLit>,
inclusive: bool,
},
Unsupported,
}
#[derive(Clone, Copy)]
pub enum MacroKind {
Println,
Print,
Eprintln,
Eprint,
Panic,
Anyhow,
Bail,
}
#[derive(Clone)]
pub enum Op {
LoadConst {
dst: Reg,
k: u16,
},
LoadInt {
dst: Reg,
v: i64,
},
LoadBool {
dst: Reg,
v: bool,
},
LoadUnit {
dst: Reg,
},
LoadUpvalue {
dst: Reg,
idx: u16,
},
LoadCell {
dst: Reg,
cell: Reg,
},
StoreCell {
cell: Reg,
src: Reg,
},
StoreUpvalue {
idx: u16,
src: Reg,
},
LoadGlobal {
dst: Reg,
idx: u32,
},
Move {
dst: Reg,
src: Reg,
},
Bin {
dst: Reg,
a: Reg,
b: Reg,
op: BinKind,
},
BinImm {
dst: Reg,
a: Reg,
imm: i64,
op: BinKind,
},
Un {
dst: Reg,
a: Reg,
op: UnKind,
},
Jump {
to: u32,
},
JumpIfFalse {
cond: Reg,
to: u32,
},
JumpIfTrue {
cond: Reg,
to: u32,
},
CmpJump {
a: Reg,
b: Reg,
op: BinKind,
to: u32,
},
CmpJumpImm {
a: Reg,
imm: i64,
op: BinKind,
to: u32,
},
CallFn {
dst: Reg,
func: u32,
base: Reg,
argc: u16,
targ: u32,
},
CallValue {
dst: Reg,
callee: Reg,
base: Reg,
argc: u16,
},
CallPath {
dst: Reg,
path: u16,
base: Reg,
argc: u16,
},
PathValue {
dst: Reg,
path: u16,
},
Method {
dst: Reg,
recv: Reg,
name: u16,
base: Reg,
argc: u16,
},
GetOrDefault {
dst: Reg,
recv: Reg,
key: Reg,
default: Reg,
},
Ret {
src: Reg,
},
MakeVec {
dst: Reg,
base: Reg,
count: u16,
},
MakeTuple {
dst: Reg,
base: Reg,
count: u16,
},
MakeArrayRepeat {
dst: Reg,
val: Reg,
count: Reg,
},
MakeRange {
dst: Reg,
start: Reg,
end: Reg,
inclusive: bool,
},
IterInit {
dst: Reg,
src: Reg,
},
ForNext {
iter: Reg,
idx: Reg,
val: Reg,
to: u32,
},
MakeStruct {
dst: Reg,
info: u16,
base: Reg,
},
MakeEnum {
dst: Reg,
info: u16,
base: Reg,
count: u16,
},
LoadEnum {
dst: Reg,
info: u16,
},
MakeClosure {
dst: Reg,
child: u16,
},
Index {
dst: Reg,
base: Reg,
key: Reg,
},
SetIndex {
base: Reg,
key: Reg,
val: Reg,
},
Deref {
dst: Reg,
src: Reg,
},
SetDeref {
target: Reg,
val: Reg,
},
GetField {
dst: Reg,
base: Reg,
member: u16,
},
SetField {
base: Reg,
member: u16,
val: Reg,
},
Try {
dst: Reg,
src: Reg,
},
Cast {
dst: Reg,
src: Reg,
ty: u16,
},
Coerce {
dst: Reg,
src: Reg,
ty: u16,
},
TestBind {
val: Reg,
pat: u16,
dst: Reg,
},
Fmt {
dst: Reg,
spec: u16,
},
MacroCall {
kind: MacroKind,
dst: Reg,
spec: u16,
},
Dbg {
dst: Reg,
base: Reg,
argc: u16,
},
Spawn {
dst: Reg,
child: u16,
},
Await {
dst: Reg,
src: Reg,
},
}
pub struct Chunk {
pub code: Vec<Op>,
pub lines: Vec<u32>,
pub file: Arc<str>,
pub num_regs: usize,
pub num_params: usize,
pub name: String,
pub module: u16,
pub consts: Vec<Const>,
pub members: Vec<Member>,
pub pats: Vec<PatInfo>,
pub fmts: Vec<FmtSpec>,
pub struct_lits: Vec<StructLit>,
pub enum_variants: Vec<EnumVariant>,
pub casts: Vec<Rc<syn::Type>>,
pub paths: Vec<(Vec<String>, Option<Rc<syn::Type>>)>,
pub names: Vec<MethodName>,
pub children: Vec<Rc<Chunk>>,
pub child_caps: Vec<Vec<CapSource>>,
pub generics: Vec<Rc<str>>,
pub call_type_args: Vec<Rc<[Rc<syn::Type>]>>,
}
impl Chunk {
pub fn empty(name: impl Into<String>) -> Chunk {
Chunk {
code: Vec::new(),
lines: Vec::new(),
file: Arc::from(""),
num_regs: 0,
num_params: 0,
name: name.into(),
module: 0,
consts: Vec::new(),
members: Vec::new(),
pats: Vec::new(),
fmts: Vec::new(),
struct_lits: Vec::new(),
enum_variants: Vec::new(),
casts: Vec::new(),
paths: Vec::new(),
names: Vec::new(),
children: Vec::new(),
child_caps: Vec::new(),
generics: Vec::new(),
call_type_args: Vec::new(),
}
}
}