cl-interpret: Literal[String] a la python
This commit is contained in:
parent
259c9f8bb6
commit
239785b322
@ -178,6 +178,7 @@ pub const Builtins: &[Builtin] = &builtins![
|
|||||||
fn len(list) @env {
|
fn len(list) @env {
|
||||||
Ok(match list {
|
Ok(match list {
|
||||||
ConValue::Empty => 0,
|
ConValue::Empty => 0,
|
||||||
|
ConValue::Str(s) => s.chars().count() as _,
|
||||||
ConValue::String(s) => s.chars().count() as _,
|
ConValue::String(s) => s.chars().count() as _,
|
||||||
ConValue::Ref(r) => {
|
ConValue::Ref(r) => {
|
||||||
return len(env, &[env.get_id(*r).ok_or(Error::StackOverflow(*r))?.clone()])
|
return len(env, &[env.get_id(*r).ok_or(Error::StackOverflow(*r))?.clone()])
|
||||||
@ -203,6 +204,7 @@ pub const Builtins: &[Builtin] = &builtins![
|
|||||||
|
|
||||||
fn chars(string) @env {
|
fn chars(string) @env {
|
||||||
Ok(match string {
|
Ok(match string {
|
||||||
|
ConValue::Str(s) => ConValue::Array(s.chars().map(Into::into).collect()),
|
||||||
ConValue::String(s) => ConValue::Array(s.chars().map(Into::into).collect()),
|
ConValue::String(s) => ConValue::Array(s.chars().map(Into::into).collect()),
|
||||||
ConValue::Ref(r) => {
|
ConValue::Ref(r) => {
|
||||||
return chars(env, &[env.get_id(*r).ok_or(Error::StackOverflow(*r))?.clone()])
|
return chars(env, &[env.get_id(*r).ok_or(Error::StackOverflow(*r))?.clone()])
|
||||||
@ -259,7 +261,15 @@ pub const Math: &[Builtin] = &builtins![
|
|||||||
Ok(match (lhs, rhs) {
|
Ok(match (lhs, rhs) {
|
||||||
(ConValue::Empty, ConValue::Empty) => ConValue::Empty,
|
(ConValue::Empty, ConValue::Empty) => ConValue::Empty,
|
||||||
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a + b),
|
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a + b),
|
||||||
(ConValue::String(a), ConValue::String(b)) => (a.to_string() + &b.to_string()).into(),
|
(ConValue::Str(a), ConValue::Str(b)) => (a.to_string() + b).into(),
|
||||||
|
(ConValue::Str(a), ConValue::String(b)) => (a.to_string() + b).into(),
|
||||||
|
(ConValue::String(a), ConValue::Str(b)) => (a.to_string() + b).into(),
|
||||||
|
(ConValue::String(a), ConValue::String(b)) => (a.to_string() + b).into(),
|
||||||
|
(ConValue::Str(s), ConValue::Char(c)) => { let mut s = s.to_string(); s.push(*c); s.into() }
|
||||||
|
(ConValue::String(s), ConValue::Char(c)) => { let mut s = s.to_string(); s.push(*c); s.into() }
|
||||||
|
(ConValue::Char(a), ConValue::Char(b)) => {
|
||||||
|
ConValue::String([a, b].into_iter().collect::<String>())
|
||||||
|
}
|
||||||
_ => Err(Error::TypeError())?
|
_ => Err(Error::TypeError())?
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -375,6 +385,9 @@ pub const Math: &[Builtin] = &builtins![
|
|||||||
(ConValue::Int(a), ConValue::Int(b)) => a.cmp(b) as _,
|
(ConValue::Int(a), ConValue::Int(b)) => a.cmp(b) as _,
|
||||||
(ConValue::Bool(a), ConValue::Bool(b)) => a.cmp(b) as _,
|
(ConValue::Bool(a), ConValue::Bool(b)) => a.cmp(b) as _,
|
||||||
(ConValue::Char(a), ConValue::Char(b)) => a.cmp(b) as _,
|
(ConValue::Char(a), ConValue::Char(b)) => a.cmp(b) as _,
|
||||||
|
(ConValue::Str(a), ConValue::Str(b)) => a.cmp(b) as _,
|
||||||
|
(ConValue::Str(a), ConValue::String(b)) => a.to_ref().cmp(b.as_str()) as _,
|
||||||
|
(ConValue::String(a), ConValue::Str(b)) => a.as_str().cmp(b.to_ref()) as _,
|
||||||
(ConValue::String(a), ConValue::String(b)) => a.cmp(b) as _,
|
(ConValue::String(a), ConValue::String(b)) => a.cmp(b) as _,
|
||||||
_ => Err(error_format!("Incomparable values: {head}, {tail}"))?
|
_ => Err(error_format!("Incomparable values: {head}, {tail}"))?
|
||||||
}))
|
}))
|
||||||
|
@ -51,8 +51,10 @@ pub enum ConValue {
|
|||||||
Bool(bool),
|
Bool(bool),
|
||||||
/// A unicode character
|
/// A unicode character
|
||||||
Char(char),
|
Char(char),
|
||||||
/// A string
|
/// A string literal
|
||||||
String(Sym),
|
Str(Sym),
|
||||||
|
/// A dynamic string
|
||||||
|
String(String),
|
||||||
/// A reference
|
/// A reference
|
||||||
Ref(usize),
|
Ref(usize),
|
||||||
/// A reference to an array
|
/// A reference to an array
|
||||||
@ -97,6 +99,7 @@ impl ConValue {
|
|||||||
ConValue::Float(_) => "f64",
|
ConValue::Float(_) => "f64",
|
||||||
ConValue::Bool(_) => "bool",
|
ConValue::Bool(_) => "bool",
|
||||||
ConValue::Char(_) => "char",
|
ConValue::Char(_) => "char",
|
||||||
|
ConValue::Str(_) => "str",
|
||||||
ConValue::String(_) => "String",
|
ConValue::String(_) => "String",
|
||||||
ConValue::Ref(_) => "Ref",
|
ConValue::Ref(_) => "Ref",
|
||||||
ConValue::Slice(_, _) => "Slice",
|
ConValue::Slice(_, _) => "Slice",
|
||||||
@ -128,6 +131,11 @@ impl ConValue {
|
|||||||
Err(Error::TypeError())?
|
Err(Error::TypeError())?
|
||||||
};
|
};
|
||||||
match self {
|
match self {
|
||||||
|
ConValue::Str(string) => string
|
||||||
|
.chars()
|
||||||
|
.nth(index as _)
|
||||||
|
.map(ConValue::Char)
|
||||||
|
.ok_or(Error::OobIndex(index as usize, string.chars().count())),
|
||||||
ConValue::String(string) => string
|
ConValue::String(string) => string
|
||||||
.chars()
|
.chars()
|
||||||
.nth(index as _)
|
.nth(index as _)
|
||||||
@ -216,6 +224,9 @@ macro cmp ($($fn:ident: $empty:literal, $op:tt);*$(;)?) {$(
|
|||||||
(Self::Float(a), Self::Float(b)) => Ok(Self::Bool(a $op b)),
|
(Self::Float(a), Self::Float(b)) => Ok(Self::Bool(a $op b)),
|
||||||
(Self::Bool(a), Self::Bool(b)) => Ok(Self::Bool(a $op b)),
|
(Self::Bool(a), Self::Bool(b)) => Ok(Self::Bool(a $op b)),
|
||||||
(Self::Char(a), Self::Char(b)) => Ok(Self::Bool(a $op b)),
|
(Self::Char(a), Self::Char(b)) => Ok(Self::Bool(a $op b)),
|
||||||
|
(Self::Str(a), Self::Str(b)) => Ok(Self::Bool(&**a $op &**b)),
|
||||||
|
(Self::Str(a), Self::String(b)) => Ok(Self::Bool(&**a $op &**b)),
|
||||||
|
(Self::String(a), Self::Str(b)) => Ok(Self::Bool(&**a $op &**b)),
|
||||||
(Self::String(a), Self::String(b)) => Ok(Self::Bool(&**a $op &**b)),
|
(Self::String(a), Self::String(b)) => Ok(Self::Bool(&**a $op &**b)),
|
||||||
_ => Err(Error::TypeError())
|
_ => Err(Error::TypeError())
|
||||||
}
|
}
|
||||||
@ -235,7 +246,7 @@ macro from ($($T:ty => $v:expr),*$(,)?) {
|
|||||||
}
|
}
|
||||||
impl From<&Sym> for ConValue {
|
impl From<&Sym> for ConValue {
|
||||||
fn from(value: &Sym) -> Self {
|
fn from(value: &Sym) -> Self {
|
||||||
ConValue::String(*value)
|
ConValue::Str(*value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
from! {
|
from! {
|
||||||
@ -243,11 +254,11 @@ from! {
|
|||||||
f64 => ConValue::Float,
|
f64 => ConValue::Float,
|
||||||
bool => ConValue::Bool,
|
bool => ConValue::Bool,
|
||||||
char => ConValue::Char,
|
char => ConValue::Char,
|
||||||
Sym => ConValue::String,
|
Sym => ConValue::Str,
|
||||||
&str => ConValue::String,
|
&str => ConValue::Str,
|
||||||
Expr => ConValue::Quote,
|
Expr => ConValue::Quote,
|
||||||
String => ConValue::String,
|
String => ConValue::String,
|
||||||
Rc<str> => ConValue::String,
|
Rc<str> => ConValue::Str,
|
||||||
Function => ConValue::Function,
|
Function => ConValue::Function,
|
||||||
Vec<ConValue> => ConValue::Tuple,
|
Vec<ConValue> => ConValue::Tuple,
|
||||||
&'static Builtin => ConValue::Builtin,
|
&'static Builtin => ConValue::Builtin,
|
||||||
@ -282,10 +293,14 @@ ops! {
|
|||||||
(ConValue::Empty, ConValue::Empty) => ConValue::Empty,
|
(ConValue::Empty, ConValue::Empty) => ConValue::Empty,
|
||||||
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_add(b)),
|
(ConValue::Int(a), ConValue::Int(b)) => ConValue::Int(a.wrapping_add(b)),
|
||||||
(ConValue::Float(a), ConValue::Float(b)) => ConValue::Float(a + b),
|
(ConValue::Float(a), ConValue::Float(b)) => ConValue::Float(a + b),
|
||||||
|
(ConValue::Str(a), ConValue::Str(b)) => (a.to_string() + &*b).into(),
|
||||||
|
(ConValue::Str(a), ConValue::String(b)) => (a.to_string() + &*b).into(),
|
||||||
|
(ConValue::String(a), ConValue::Str(b)) => (a.to_string() + &*b).into(),
|
||||||
(ConValue::String(a), ConValue::String(b)) => (a.to_string() + &*b).into(),
|
(ConValue::String(a), ConValue::String(b)) => (a.to_string() + &*b).into(),
|
||||||
|
(ConValue::Str(s), ConValue::Char(c)) => { let mut s = s.to_string(); s.push(c); s.into() }
|
||||||
(ConValue::String(s), ConValue::Char(c)) => { let mut s = s.to_string(); s.push(c); s.into() }
|
(ConValue::String(s), ConValue::Char(c)) => { let mut s = s.to_string(); s.push(c); s.into() }
|
||||||
(ConValue::Char(a), ConValue::Char(b)) => {
|
(ConValue::Char(a), ConValue::Char(b)) => {
|
||||||
ConValue::String([a, b].into_iter().collect::<String>().into())
|
ConValue::String([a, b].into_iter().collect::<String>())
|
||||||
}
|
}
|
||||||
_ => Err(Error::TypeError())?
|
_ => Err(Error::TypeError())?
|
||||||
]
|
]
|
||||||
@ -354,6 +369,7 @@ impl std::fmt::Display for ConValue {
|
|||||||
ConValue::Float(v) => v.fmt(f),
|
ConValue::Float(v) => v.fmt(f),
|
||||||
ConValue::Bool(v) => v.fmt(f),
|
ConValue::Bool(v) => v.fmt(f),
|
||||||
ConValue::Char(v) => v.fmt(f),
|
ConValue::Char(v) => v.fmt(f),
|
||||||
|
ConValue::Str(v) => v.fmt(f),
|
||||||
ConValue::String(v) => v.fmt(f),
|
ConValue::String(v) => v.fmt(f),
|
||||||
ConValue::Ref(v) => write!(f, "&<{}>", v),
|
ConValue::Ref(v) => write!(f, "&<{}>", v),
|
||||||
ConValue::Slice(id, len) => write!(f, "&<{id}>[{len}..]"),
|
ConValue::Slice(id, len) => write!(f, "&<{id}>[{len}..]"),
|
||||||
|
@ -699,7 +699,7 @@ fn cast(env: &Environment, value: ConValue, ty: Sym) -> IResult<ConValue> {
|
|||||||
// TODO: This, better
|
// TODO: This, better
|
||||||
ConValue::Float(_) if ty.starts_with('f') => return Ok(value),
|
ConValue::Float(_) if ty.starts_with('f') => return Ok(value),
|
||||||
ConValue::Float(f) => f as _,
|
ConValue::Float(f) => f as _,
|
||||||
_ if (*ty).eq("str") => return Ok(ConValue::String(format!("{value}").into())),
|
_ if (*ty).eq("str") => return Ok(ConValue::Str(format!("{value}").into())),
|
||||||
_ => Err(Error::TypeError())?,
|
_ => Err(Error::TypeError())?,
|
||||||
};
|
};
|
||||||
Ok(match &*ty {
|
Ok(match &*ty {
|
||||||
@ -958,7 +958,7 @@ impl Interpret for For {
|
|||||||
&ConValue::Slice(head, len) => Box::new((head..head + len).map(ConValue::Ref)),
|
&ConValue::Slice(head, len) => Box::new((head..head + len).map(ConValue::Ref)),
|
||||||
// In the production compiler this may be fully unrolled
|
// In the production compiler this may be fully unrolled
|
||||||
ConValue::Tuple(t) => Box::new(t.iter().cloned()),
|
ConValue::Tuple(t) => Box::new(t.iter().cloned()),
|
||||||
ConValue::String(s) => Box::new(s.chars().map(ConValue::Char)),
|
ConValue::Str(s) => Box::new(s.chars().map(ConValue::Char)),
|
||||||
_ => Err(Error::TypeError())?,
|
_ => Err(Error::TypeError())?,
|
||||||
};
|
};
|
||||||
loop {
|
loop {
|
||||||
|
@ -139,6 +139,9 @@ pub fn append_sub(
|
|||||||
(Pattern::Literal(Literal::Int(a)), ConValue::Int(b)) => {
|
(Pattern::Literal(Literal::Int(a)), ConValue::Int(b)) => {
|
||||||
(b == *a as _).then_some(()).ok_or(Error::NotAssignable())
|
(b == *a as _).then_some(()).ok_or(Error::NotAssignable())
|
||||||
}
|
}
|
||||||
|
(Pattern::Literal(Literal::String(a)), ConValue::Str(b)) => {
|
||||||
|
(*a == *b).then_some(()).ok_or(Error::NotAssignable())
|
||||||
|
}
|
||||||
(Pattern::Literal(Literal::String(a)), ConValue::String(b)) => {
|
(Pattern::Literal(Literal::String(a)), ConValue::String(b)) => {
|
||||||
(*a == *b).then_some(()).ok_or(Error::NotAssignable())
|
(*a == *b).then_some(()).ok_or(Error::NotAssignable())
|
||||||
}
|
}
|
||||||
@ -157,6 +160,9 @@ pub fn append_sub(
|
|||||||
(Pattern::Literal(Literal::Float(a)), ConValue::Float(b)) => {
|
(Pattern::Literal(Literal::Float(a)), ConValue::Float(b)) => {
|
||||||
(b < *a as _).then_some(()).ok_or(Error::NotAssignable())
|
(b < *a as _).then_some(()).ok_or(Error::NotAssignable())
|
||||||
}
|
}
|
||||||
|
(Pattern::Literal(Literal::String(a)), ConValue::Str(b)) => {
|
||||||
|
(&*b < a).then_some(()).ok_or(Error::NotAssignable())
|
||||||
|
}
|
||||||
(Pattern::Literal(Literal::String(a)), ConValue::String(b)) => {
|
(Pattern::Literal(Literal::String(a)), ConValue::String(b)) => {
|
||||||
(&*b < a).then_some(()).ok_or(Error::NotAssignable())
|
(&*b < a).then_some(()).ok_or(Error::NotAssignable())
|
||||||
}
|
}
|
||||||
@ -207,10 +213,17 @@ pub fn append_sub(
|
|||||||
(
|
(
|
||||||
Pattern::Literal(Literal::String(a)),
|
Pattern::Literal(Literal::String(a)),
|
||||||
Pattern::Literal(Literal::String(c)),
|
Pattern::Literal(Literal::String(c)),
|
||||||
ConValue::String(b),
|
ConValue::Str(b),
|
||||||
) => (a.as_str() <= b.to_ref() && b.to_ref() < c.as_str())
|
) => (a.as_str() <= b.to_ref() && b.to_ref() < c.as_str())
|
||||||
.then_some(())
|
.then_some(())
|
||||||
.ok_or(Error::NotAssignable()),
|
.ok_or(Error::NotAssignable()),
|
||||||
|
(
|
||||||
|
Pattern::Literal(Literal::String(a)),
|
||||||
|
Pattern::Literal(Literal::String(c)),
|
||||||
|
ConValue::String(b),
|
||||||
|
) => (a.as_str() <= b.as_str() && b.as_str() < c.as_str())
|
||||||
|
.then_some(())
|
||||||
|
.ok_or(Error::NotAssignable()),
|
||||||
_ => Err(Error::NotAssignable()),
|
_ => Err(Error::NotAssignable()),
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -239,10 +252,17 @@ pub fn append_sub(
|
|||||||
(
|
(
|
||||||
Pattern::Literal(Literal::String(a)),
|
Pattern::Literal(Literal::String(a)),
|
||||||
Pattern::Literal(Literal::String(c)),
|
Pattern::Literal(Literal::String(c)),
|
||||||
ConValue::String(b),
|
ConValue::Str(b),
|
||||||
) => (a.as_str() <= b.to_ref() && b.to_ref() <= c.as_str())
|
) => (a.as_str() <= b.to_ref() && b.to_ref() <= c.as_str())
|
||||||
.then_some(())
|
.then_some(())
|
||||||
.ok_or(Error::NotAssignable()),
|
.ok_or(Error::NotAssignable()),
|
||||||
|
(
|
||||||
|
Pattern::Literal(Literal::String(a)),
|
||||||
|
Pattern::Literal(Literal::String(c)),
|
||||||
|
ConValue::String(b),
|
||||||
|
) => (a.as_str() <= b.as_str() && b.as_str() <= c.as_str())
|
||||||
|
.then_some(())
|
||||||
|
.ok_or(Error::NotAssignable()),
|
||||||
_ => Err(Error::NotAssignable()),
|
_ => Err(Error::NotAssignable()),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -26,23 +26,29 @@ pub fn run(args: Args) -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
fn eval(string) @env {
|
fn eval(string) @env {
|
||||||
use cl_interpret::error::Error;
|
use cl_interpret::error::Error;
|
||||||
let string = match *string {
|
let string = match string {
|
||||||
ConValue::String(string) => string,
|
ConValue::Str(string) => string.to_ref(),
|
||||||
|
ConValue::String(string) => string.as_str(),
|
||||||
ConValue::Ref(v) => {
|
ConValue::Ref(v) => {
|
||||||
let string = env.get_id(v).cloned().unwrap_or_default();
|
let string = env.get_id(*v).cloned().unwrap_or_default();
|
||||||
return eval(env, &[string])
|
return eval(env, &[string])
|
||||||
}
|
}
|
||||||
_ => Err(Error::TypeError())?
|
_ => Err(Error::TypeError())?
|
||||||
};
|
};
|
||||||
match Parser::new("eval", Lexer::new(string.to_ref())).parse::<cl_ast::Stmt>() {
|
match Parser::new("eval", Lexer::new(string)).parse::<cl_ast::Stmt>() {
|
||||||
Err(e) => Ok(ConValue::String(format!("{e}").into())),
|
Err(e) => Ok(ConValue::Str(format!("{e}").into())),
|
||||||
Ok(v) => v.interpret(env),
|
Ok(v) => v.interpret(env),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes a file
|
/// Executes a file
|
||||||
fn import(ConValue::String(path)) @env {
|
fn import(path) @env {
|
||||||
load_file(env, &**path).or(Ok(ConValue::Empty))
|
use cl_interpret::error::Error;
|
||||||
|
match path {
|
||||||
|
ConValue::Str(path) => load_file(env, &**path).or(Ok(ConValue::Empty)),
|
||||||
|
ConValue::String(path) => load_file(env, &**path).or(Ok(ConValue::Empty)),
|
||||||
|
_ => Err(Error::TypeError())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn putchar(ConValue::Char(c)) {
|
fn putchar(ConValue::Char(c)) {
|
||||||
@ -51,12 +57,18 @@ pub fn run(args: Args) -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a line of input from stdin
|
/// Gets a line of input from stdin
|
||||||
fn get_line(ConValue::String(prompt)) {
|
fn get_line(prompt) {
|
||||||
match repline::Repline::new("", prompt.to_ref(), "").read() {
|
use cl_interpret::error::Error;
|
||||||
Ok(line) => Ok(ConValue::String(line.into())),
|
let prompt = match prompt {
|
||||||
Err(repline::Error::CtrlD(line)) => Ok(ConValue::String(line.into())),
|
ConValue::Str(prompt) => prompt.to_ref(),
|
||||||
|
ConValue::String(prompt) => prompt.as_str(),
|
||||||
|
_ => Err(Error::TypeError())?,
|
||||||
|
};
|
||||||
|
match repline::Repline::new("", prompt, "").read() {
|
||||||
|
Ok(line) => Ok(ConValue::String(line)),
|
||||||
|
Err(repline::Error::CtrlD(line)) => Ok(ConValue::String(line)),
|
||||||
Err(repline::Error::CtrlC(_)) => Err(cl_interpret::error::Error::Break(ConValue::Empty)),
|
Err(repline::Error::CtrlC(_)) => Err(cl_interpret::error::Error::Break(ConValue::Empty)),
|
||||||
Err(e) => Ok(ConValue::String(e.to_string().into())),
|
Err(e) => Ok(ConValue::Str(e.to_string().into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
fn f(__fmt: str) -> str {
|
fn f(__fmt: str) -> str {
|
||||||
let __out = "";
|
let __out = "";
|
||||||
let __expr = "";
|
let __expr = "";
|
||||||
|
let __label = "";
|
||||||
let __depth = 0;
|
let __depth = 0;
|
||||||
for __c in chars(__fmt) {
|
for __c in chars(__fmt) {
|
||||||
match __c {
|
match __c {
|
||||||
@ -14,19 +15,26 @@ fn f(__fmt: str) -> str {
|
|||||||
'}' => {
|
'}' => {
|
||||||
__depth -= 1
|
__depth -= 1
|
||||||
if __depth <= 0 {
|
if __depth <= 0 {
|
||||||
__out += fmt(eval(__expr))
|
__out = fmt(__out, __label, eval(__expr));
|
||||||
__expr = ""
|
(__expr, __label) = ("", "");
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
':' => if __depth == 1 {
|
':' => if __depth == 1 && __label.len() == 0 {
|
||||||
__out += __expr + ": "
|
__label = __expr + __c
|
||||||
|
continue
|
||||||
|
},
|
||||||
|
'=' => if __depth == 1 && __label.len() == 0 {
|
||||||
|
__label = __expr + __c
|
||||||
|
continue
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if __depth > 0 {
|
match (__depth, __label.len()) {
|
||||||
__expr += __c
|
(0, _) => __out += __c,
|
||||||
} else __out += __c;
|
(_, 0) => __expr += __c,
|
||||||
|
(_, _) => __label += __c,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
__out
|
__out
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user