fix more syntax v2 bugs, update docs
This commit is contained in:
parent
bf37d7305c
commit
d1a6fb364e
11 changed files with 544 additions and 528 deletions
|
@ -4,4 +4,5 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
log.workspace = true
|
||||
tiny-skia = { version = "0.11.4", default-features = false, features = ["no-std-float"] }
|
||||
|
|
|
@ -13,6 +13,7 @@ pub enum Opcode {
|
|||
False,
|
||||
True,
|
||||
Number, // (float: f32)
|
||||
Rgba, // (r: u8, g: u8, b: u8, a: u8)
|
||||
|
||||
// Duplicate existing values.
|
||||
/// Push a value relative to the bottom of the current stack window.
|
||||
|
@ -26,6 +27,9 @@ pub enum Opcode {
|
|||
/// Set the value of a definition.
|
||||
SetDef, // (index: u16)
|
||||
|
||||
// Create lists.
|
||||
List, // (len: u16)
|
||||
|
||||
// Create literal functions.
|
||||
Function, // (params: u8, then: u16), at `then`: (local_count: u8, capture_count: u8, captures: [(source: u8, index: u8); capture_count])
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use core::{
|
|||
};
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use log::info;
|
||||
|
||||
use crate::{
|
||||
ast::{Ast, NodeId, NodeKind},
|
||||
|
@ -98,12 +99,11 @@ pub fn compile_expr<'a>(c: &mut Compiler<'a>, src: &Source<'a>, node_id: NodeId)
|
|||
// as they may also contain commas and other trivia.
|
||||
NodeKind::Param => unreachable!("Param node should never be emitted"),
|
||||
|
||||
NodeKind::Color => unsupported(c, src, node_id, "color literals are not implemented yet"),
|
||||
|
||||
NodeKind::Ident => compile_ident(c, src, node_id),
|
||||
NodeKind::Number => compile_number(c, src, node_id),
|
||||
NodeKind::Tag => compile_tag(c, src, node_id),
|
||||
NodeKind::List => unsupported(c, src, node_id, "list literals are not implemented yet"),
|
||||
NodeKind::Number => compile_number(c, src, node_id),
|
||||
NodeKind::Color => compile_color(c, src, node_id),
|
||||
NodeKind::List => compile_list(c, src, node_id),
|
||||
|
||||
NodeKind::Unary => compile_unary(c, src, node_id),
|
||||
NodeKind::Binary => compile_binary(c, src, node_id),
|
||||
|
@ -200,18 +200,6 @@ fn compile_ident<'a>(c: &mut Compiler<'a>, src: &Source<'a>, node_id: NodeId) ->
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_number(c: &mut Compiler, src: &Source, node_id: NodeId) -> CompileResult {
|
||||
let literal = src.ast.span(node_id).slice(src.code);
|
||||
let float: f32 = literal
|
||||
.parse()
|
||||
.expect("the parser should've gotten us a string parsable by the stdlib");
|
||||
|
||||
c.chunk.emit_opcode(Opcode::Number)?;
|
||||
c.chunk.emit_f32(float)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_tag(c: &mut Compiler, src: &Source, node_id: NodeId) -> CompileResult {
|
||||
let tag = src.ast.span(node_id).slice(src.code);
|
||||
|
||||
|
@ -230,6 +218,79 @@ fn compile_tag(c: &mut Compiler, src: &Source, node_id: NodeId) -> CompileResult
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_number(c: &mut Compiler, src: &Source, node_id: NodeId) -> CompileResult {
|
||||
let literal = src.ast.span(node_id).slice(src.code);
|
||||
if let Ok(float) = literal.parse() {
|
||||
c.chunk.emit_opcode(Opcode::Number)?;
|
||||
c.chunk.emit_f32(float)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_color(c: &mut Compiler, src: &Source, node_id: NodeId) -> CompileResult {
|
||||
let literal = src.ast.span(node_id).slice(src.code);
|
||||
|
||||
let hex = &literal[1..];
|
||||
let bytes: [u8; 4] = u32::from_str_radix(hex, 16)
|
||||
.ok()
|
||||
.and_then(|num| match hex.len() {
|
||||
3 => Some([
|
||||
(((num & 0xF00) >> 8) * 0x11) as u8,
|
||||
(((num & 0x0F0) >> 4) * 0x11) as u8,
|
||||
((num & 0x00F) * 0x11) as u8,
|
||||
0xFF,
|
||||
]),
|
||||
4 => Some([
|
||||
(((num & 0xF000) >> 12) * 0x11) as u8,
|
||||
(((num & 0x0F00) >> 8) * 0x11) as u8,
|
||||
(((num & 0x00F0) >> 4) * 0x11) as u8,
|
||||
((num & 0x000F) * 0x11) as u8,
|
||||
]),
|
||||
6 => Some([
|
||||
((num & 0xFF0000) >> 16) as u8,
|
||||
((num & 0x00FF00) >> 8) as u8,
|
||||
(num & 0x0000FF) as u8,
|
||||
0xFF,
|
||||
]),
|
||||
8 => Some([
|
||||
((num & 0xFF000000) >> 24) as u8,
|
||||
((num & 0x00FF0000) >> 16) as u8,
|
||||
((num & 0x0000FF00) >> 8) as u8,
|
||||
(num & 0x000000FF) as u8,
|
||||
]),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or([0, 0, 0, 0]);
|
||||
|
||||
c.chunk.emit_opcode(Opcode::Rgba)?;
|
||||
c.chunk.emit_bytes(&bytes)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_list<'a>(c: &mut Compiler<'a>, src: &Source<'a>, node_id: NodeId) -> CompileResult {
|
||||
let mut walk = src.ast.walk(node_id);
|
||||
|
||||
let mut len = 0;
|
||||
while let Some(expr) = walk.node() {
|
||||
compile_expr(c, src, expr)?;
|
||||
len += 1;
|
||||
}
|
||||
|
||||
let len = u16::try_from(len).unwrap_or_else(|_| {
|
||||
// For all practical intents and purposes, this should never happen---you'll most likely
|
||||
// run into the chunk length limit first.
|
||||
c.emit(Diagnostic::error(src.ast.span(node_id), "list is too long"));
|
||||
0
|
||||
});
|
||||
|
||||
c.chunk.emit_opcode(Opcode::List)?;
|
||||
c.chunk.emit_u16(len)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_unary<'a>(c: &mut Compiler<'a>, src: &Source<'a>, node_id: NodeId) -> CompileResult {
|
||||
let mut walk = src.ast.walk(node_id);
|
||||
let Some(op) = walk.node() else { return Ok(()) };
|
||||
|
|
|
@ -17,16 +17,16 @@ impl<'a> Lexer<'a> {
|
|||
pub fn new(lexis: Lexis, input: &'a SourceCode) -> Self {
|
||||
Self {
|
||||
lexis,
|
||||
diagnostics: Vec::new(),
|
||||
diagnostics: Vec::with_capacity(16),
|
||||
input,
|
||||
position: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn current(&self) -> char {
|
||||
self.input[self.position as usize..]
|
||||
.chars()
|
||||
.next()
|
||||
self.input
|
||||
.get(self.position as usize..)
|
||||
.and_then(|s| s.chars().next())
|
||||
.unwrap_or('\0')
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ fn whitespace_and_comments(l: &mut Lexer<'_>) {
|
|||
let position = l.position;
|
||||
l.advance();
|
||||
if l.current() == '-' {
|
||||
while l.current() != '\n' {
|
||||
while l.current() != '\n' && l.current() != '\0' {
|
||||
l.advance();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -143,7 +143,8 @@ pub mod fns {
|
|||
0x88 Nary "rgbaB" => rgba_b,
|
||||
0x89 Nary "rgbaA" => rgba_a,
|
||||
|
||||
0x90 Nary "list" => list,
|
||||
// NOTE: Not used right now, has been replaced with Opcode::List.
|
||||
0x90 Nary "list (unused)" => list,
|
||||
|
||||
0xc0 Nary "toShape" => to_shape_f,
|
||||
0xc1 Nary "line" => line,
|
||||
|
|
|
@ -5,11 +5,12 @@ use core::{
|
|||
};
|
||||
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use log::info;
|
||||
|
||||
use crate::{
|
||||
bytecode::{self, Defs, Opcode, CAPTURE_CAPTURE, CAPTURE_LOCAL},
|
||||
system::{ChunkId, System},
|
||||
value::{BytecodeLoc, Closure, FunctionName, Ref, RefId, Rgba, Value, Vec4},
|
||||
value::{BytecodeLoc, Closure, FunctionName, List, Ref, RefId, Rgba, Value, Vec4},
|
||||
};
|
||||
|
||||
pub struct VmLimits {
|
||||
|
@ -208,6 +209,19 @@ impl Vm {
|
|||
self.push(Value::Number(x))?;
|
||||
}
|
||||
|
||||
Opcode::Rgba => {
|
||||
let r = chunk.read_u8(&mut pc)?;
|
||||
let g = chunk.read_u8(&mut pc)?;
|
||||
let b = chunk.read_u8(&mut pc)?;
|
||||
let a = chunk.read_u8(&mut pc)?;
|
||||
self.push(Value::Rgba(Rgba {
|
||||
r: r as f32 / 255.0,
|
||||
g: g as f32 / 255.0,
|
||||
b: b as f32 / 255.0,
|
||||
a: a as f32 / 255.0,
|
||||
}))?;
|
||||
}
|
||||
|
||||
Opcode::Local => {
|
||||
let index = chunk.read_u8(&mut pc)? as usize;
|
||||
let value = self.get(bottom + index)?;
|
||||
|
@ -246,6 +260,20 @@ impl Vm {
|
|||
}
|
||||
}
|
||||
|
||||
Opcode::List => {
|
||||
let len = chunk.read_u16(&mut pc)? as usize;
|
||||
let bottom = self.stack.len().checked_sub(len).ok_or_else(|| {
|
||||
self.create_exception(
|
||||
"corrupted bytecode (list has more elements than stack)",
|
||||
)
|
||||
})?;
|
||||
let elements = self.stack[bottom..].to_vec();
|
||||
self.stack.resize_with(bottom, || unreachable!());
|
||||
self.track_array(&elements)?;
|
||||
let id = self.create_ref(Ref::List(List { elements }))?;
|
||||
self.push(Value::Ref(id))?;
|
||||
}
|
||||
|
||||
Opcode::Function => {
|
||||
let param_count = chunk.read_u8(&mut pc)?;
|
||||
let then = chunk.read_u16(&mut pc)? as usize;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue