mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
simple literals in editor ast
This commit is contained in:
parent
a174137351
commit
8b289f3398
6 changed files with 291 additions and 8 deletions
|
@ -1486,7 +1486,7 @@ fn flatten_str_literal<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
||||
pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
||||
match expr {
|
||||
ast::Expr::Var { .. } => true,
|
||||
ast::Expr::Access(sub_expr, _) => is_valid_interpolation(sub_expr),
|
||||
|
|
|
@ -12,7 +12,7 @@ pub struct Region {
|
|||
}
|
||||
|
||||
impl Region {
|
||||
pub fn zero() -> Self {
|
||||
pub const fn zero() -> Self {
|
||||
Region {
|
||||
start_line: 0,
|
||||
end_line: 0,
|
||||
|
|
|
@ -24,6 +24,18 @@ pub enum IntStyle {
|
|||
Binary,
|
||||
}
|
||||
|
||||
impl IntStyle {
|
||||
pub fn from_base(base: roc_parse::ast::Base) -> Self {
|
||||
use roc_parse::ast::Base;
|
||||
match base {
|
||||
Base::Decimal => Self::Decimal,
|
||||
Base::Octal => Self::Octal,
|
||||
Base::Hex => Self::Hex,
|
||||
Base::Binary => Self::Binary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum IntVal {
|
||||
I64(i64),
|
||||
|
@ -237,11 +249,7 @@ pub struct PatId {
|
|||
slot: ExprPoolSlot, // TODO PatPoolSlot
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct ExprId {
|
||||
page_id: ExprPoolId,
|
||||
slot: ExprPoolSlot,
|
||||
}
|
||||
pub type ExprId = NodeId<Expr2>;
|
||||
|
||||
// We have a maximum of 65K pages.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
|
|
|
@ -0,0 +1,274 @@
|
|||
use crate::ast::{Expr2, ExprId, FloatVal, IntStyle, IntVal};
|
||||
use crate::pool::{Pool, PoolStr, PoolVec};
|
||||
use roc_can::expr::Output;
|
||||
use roc_can::num::{finish_parsing_base, finish_parsing_float, finish_parsing_int};
|
||||
use roc_can::scope::Scope;
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::operator::CalledVia;
|
||||
use roc_module::symbol::{IdentIds, ModuleId, ModuleIds, Symbol};
|
||||
use roc_parse::ast::StrLiteral;
|
||||
use roc_region::all::{Located, Region};
|
||||
use roc_types::subs::{VarStore, Variable};
|
||||
|
||||
pub struct Env<'a> {
|
||||
var_store: VarStore,
|
||||
problems: Vec<()>,
|
||||
pool: Pool,
|
||||
module_ids: &'a ModuleIds,
|
||||
}
|
||||
|
||||
const ZERO: Region = Region::zero();
|
||||
|
||||
pub fn from_parse_expr<'a>(
|
||||
env: &mut Env<'a>,
|
||||
scope: &mut Scope,
|
||||
parse_expr: &'a roc_parse::ast::Expr<'a>,
|
||||
) -> (crate::ast::ExprId, Output) {
|
||||
use roc_parse::ast::Expr::*;
|
||||
match parse_expr {
|
||||
Float(string) => {
|
||||
match finish_parsing_float(string) {
|
||||
Ok(float) => {
|
||||
let expr = Expr2::Float {
|
||||
number: FloatVal::F64(float),
|
||||
var: env.var_store.fresh(),
|
||||
};
|
||||
|
||||
(env.pool.add(expr), Output::default())
|
||||
}
|
||||
Err((_raw, _error)) => {
|
||||
// emit runtime error
|
||||
// let runtime_error = InvalidFloat(error, ZERO, raw.into());
|
||||
//
|
||||
// env.problem(Problem::RuntimeError(runtime_error.clone()));
|
||||
//
|
||||
// Expr::RuntimeError(runtime_error)
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
Num(string) => {
|
||||
match finish_parsing_int(string) {
|
||||
Ok(int) => {
|
||||
let expr = Expr2::SmallInt {
|
||||
number: IntVal::I64(int),
|
||||
var: env.var_store.fresh(),
|
||||
// TODO non-hardcode
|
||||
style: IntStyle::Decimal,
|
||||
text: PoolStr::new(string, &mut env.pool),
|
||||
};
|
||||
|
||||
(env.pool.add(expr), Output::default())
|
||||
}
|
||||
Err((_raw, _error)) => {
|
||||
// emit runtime error
|
||||
// let runtime_error = InvalidFloat(error, ZERO, raw.into());
|
||||
//
|
||||
// env.problem(Problem::RuntimeError(runtime_error.clone()));
|
||||
//
|
||||
// Expr::RuntimeError(runtime_error)
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
NonBase10Int {
|
||||
string,
|
||||
base,
|
||||
is_negative,
|
||||
} => {
|
||||
match finish_parsing_base(string, *base, *is_negative) {
|
||||
Ok(int) => {
|
||||
let expr = Expr2::SmallInt {
|
||||
number: IntVal::I64(int),
|
||||
var: env.var_store.fresh(),
|
||||
// TODO non-hardcode
|
||||
style: IntStyle::from_base(*base),
|
||||
text: PoolStr::new(string, &mut env.pool),
|
||||
};
|
||||
|
||||
(env.pool.add(expr), Output::default())
|
||||
}
|
||||
Err((_raw, _error)) => {
|
||||
// emit runtime error
|
||||
// let runtime_error = InvalidFloat(error, ZERO, raw.into());
|
||||
//
|
||||
// env.problem(Problem::RuntimeError(runtime_error.clone()));
|
||||
//
|
||||
// Expr::RuntimeError(runtime_error)
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Str(literal) => flatten_str_literal(env, scope, &literal),
|
||||
|
||||
// /// string literals of length up to 30B
|
||||
// SmallStr(ArrayString<U30>), // 31B
|
||||
// /// string literals of length 31B or more
|
||||
// Str(PoolStr), // 8B
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_str_literal<'a>(
|
||||
env: &mut Env<'a>,
|
||||
scope: &mut Scope,
|
||||
literal: &StrLiteral<'a>,
|
||||
) -> (ExprId, Output) {
|
||||
use roc_parse::ast::StrLiteral::*;
|
||||
|
||||
match literal {
|
||||
PlainLine(str_slice) => {
|
||||
// TODO use smallstr
|
||||
let expr = Expr2::Str(PoolStr::new(str_slice, &mut env.pool));
|
||||
|
||||
(env.pool.add(expr), Output::default())
|
||||
}
|
||||
Line(segments) => flatten_str_lines(env, scope, &[segments]),
|
||||
Block(lines) => flatten_str_lines(env, scope, lines),
|
||||
}
|
||||
}
|
||||
|
||||
enum StrSegment {
|
||||
Interpolation(ExprId),
|
||||
Plaintext(PoolStr),
|
||||
}
|
||||
|
||||
fn flatten_str_lines<'a>(
|
||||
env: &mut Env<'a>,
|
||||
scope: &mut Scope,
|
||||
lines: &[&[roc_parse::ast::StrSegment<'a>]],
|
||||
) -> (ExprId, Output) {
|
||||
use roc_parse::ast::StrSegment::*;
|
||||
|
||||
let mut buf = String::new();
|
||||
let mut segments = Vec::new();
|
||||
let mut output = Output::default();
|
||||
|
||||
for line in lines {
|
||||
for segment in line.iter() {
|
||||
match segment {
|
||||
Plaintext(string) => {
|
||||
buf.push_str(string);
|
||||
}
|
||||
Unicode(loc_hex_digits) => match u32::from_str_radix(loc_hex_digits.value, 16) {
|
||||
Ok(code_pt) => match std::char::from_u32(code_pt) {
|
||||
Some(ch) => {
|
||||
buf.push(ch);
|
||||
}
|
||||
None => {
|
||||
// env.problem(Problem::InvalidUnicodeCodePoint(loc_hex_digits.region));
|
||||
//
|
||||
// return (
|
||||
// Expr::RuntimeError(RuntimeError::InvalidUnicodeCodePoint(
|
||||
// loc_hex_digits.region,
|
||||
// )),
|
||||
// output,
|
||||
// );
|
||||
todo!()
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
// env.problem(Problem::InvalidHexadecimal(loc_hex_digits.region));
|
||||
//
|
||||
// return (
|
||||
// Expr::RuntimeError(RuntimeError::InvalidHexadecimal(
|
||||
// loc_hex_digits.region,
|
||||
// )),
|
||||
// output,
|
||||
// );
|
||||
todo!()
|
||||
}
|
||||
},
|
||||
Interpolated(loc_expr) => {
|
||||
if roc_can::expr::is_valid_interpolation(loc_expr.value) {
|
||||
// Interpolations desugar to Str.concat calls
|
||||
output.references.calls.insert(Symbol::STR_CONCAT);
|
||||
|
||||
if !buf.is_empty() {
|
||||
segments.push(StrSegment::Plaintext(PoolStr::new(&buf, &mut env.pool)));
|
||||
|
||||
buf = String::new();
|
||||
}
|
||||
|
||||
let (loc_expr, new_output) = from_parse_expr(env, scope, loc_expr.value);
|
||||
|
||||
output.union(new_output);
|
||||
|
||||
segments.push(StrSegment::Interpolation(loc_expr));
|
||||
} else {
|
||||
// env.problem(Problem::InvalidInterpolation(loc_expr.region));
|
||||
//
|
||||
// return (
|
||||
// Expr::RuntimeError(RuntimeError::InvalidInterpolation(loc_expr.region)),
|
||||
// output,
|
||||
// );
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
EscapedChar(escaped) => buf.push(roc_can::expr::unescape_char(escaped)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !buf.is_empty() {
|
||||
segments.push(StrSegment::Plaintext(PoolStr::new(&buf, &mut env.pool)));
|
||||
}
|
||||
|
||||
(desugar_str_segments(env, segments), output)
|
||||
}
|
||||
|
||||
/// Resolve stirng interpolations by desugaring a sequence of StrSegments
|
||||
/// into nested calls to Str.concat
|
||||
fn desugar_str_segments<'a>(env: &mut Env<'a>, segments: Vec<StrSegment>) -> ExprId {
|
||||
use StrSegment::*;
|
||||
|
||||
let pool = &mut env.pool;
|
||||
let var_store = &mut env.var_store;
|
||||
|
||||
let mut iter = segments.into_iter().rev();
|
||||
let mut expr_id = match iter.next() {
|
||||
Some(Plaintext(pool_str)) => {
|
||||
let expr = Expr2::Str(pool_str);
|
||||
|
||||
pool.add(expr)
|
||||
}
|
||||
Some(Interpolation(expr_id)) => expr_id,
|
||||
None => {
|
||||
// No segments? Empty string!
|
||||
|
||||
let pool_str = PoolStr::new("", pool);
|
||||
let expr = Expr2::Str(pool_str);
|
||||
|
||||
pool.add(expr)
|
||||
}
|
||||
};
|
||||
|
||||
for seg in iter {
|
||||
let new_expr_id = match seg {
|
||||
Plaintext(string) => pool.add(Expr2::Str(string)),
|
||||
Interpolation(expr_id) => expr_id,
|
||||
};
|
||||
|
||||
let concat_expr_id = pool.add(Expr2::Var(Symbol::STR_CONCAT));
|
||||
|
||||
let args = vec![
|
||||
(var_store.fresh(), new_expr_id),
|
||||
(var_store.fresh(), expr_id),
|
||||
];
|
||||
let args = PoolVec::new(args.into_iter(), pool);
|
||||
|
||||
let expr = Expr2::Call {
|
||||
args,
|
||||
expr: concat_expr_id,
|
||||
expr_var: var_store.fresh(),
|
||||
fn_var: var_store.fresh(),
|
||||
closure_var: var_store.fresh(),
|
||||
called_via: CalledVia::Space,
|
||||
};
|
||||
|
||||
expr_id = pool.add(expr);
|
||||
}
|
||||
|
||||
expr_id
|
||||
}
|
|
@ -32,6 +32,7 @@ use winit::event_loop::ControlFlow;
|
|||
|
||||
pub mod ast;
|
||||
mod buffer;
|
||||
pub mod expr;
|
||||
pub mod file;
|
||||
mod keyboard_input;
|
||||
pub mod pool;
|
||||
|
|
|
@ -228,7 +228,7 @@ fn pool_vec_size() {
|
|||
}
|
||||
|
||||
impl<'a, T: 'a + Sized> PoolVec<T> {
|
||||
pub fn new<I: ExactSizeIterator<Item = T>, S>(nodes: I, pool: &mut Pool) -> Self {
|
||||
pub fn new<I: ExactSizeIterator<Item = T>>(nodes: I, pool: &mut Pool) -> Self {
|
||||
debug_assert!(nodes.len() <= u32::MAX as usize);
|
||||
debug_assert!(size_of::<T>() <= NODE_BYTES);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue