feat: get string interning working

Co-authored-by: Kasey White <kwhitemsg@gmail.com>
This commit is contained in:
rvcas 2022-06-01 01:09:28 -04:00
parent 581b8fc85d
commit c7037ff8d9
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
2 changed files with 52 additions and 55 deletions

View File

@ -144,8 +144,6 @@ impl Encode for &Constant {
} }
// there is no char constant tag // there is no char constant tag
Constant::Char(c) => { Constant::Char(c) => {
c.encode(e)?;
let mut b = [0; 4]; let mut b = [0; 4];
let s = c.encode_utf8(&mut b); let s = c.encode_utf8(&mut b);

View File

@ -2,10 +2,13 @@ use std::{collections::HashMap, str::FromStr};
use combine::{ use combine::{
attempt, between, choice, many1, attempt, between, choice, many1,
parser::char::{alpha_num, digit, hex_digit, space, spaces, string}, parser::{
char::{alpha_num, digit, hex_digit, space, spaces, string},
combinator::no_partial,
},
skip_many1, skip_many1,
stream::position, stream::{position, state},
token, EasyParser, ParseError, Parser, Stream, token, ParseError, Parser, Stream,
}; };
use crate::{ use crate::{
@ -18,6 +21,8 @@ struct ParserState {
current_unique: isize, current_unique: isize,
} }
type StateStream<Input> = state::Stream<Input, ParserState>;
impl ParserState { impl ParserState {
fn new() -> Self { fn new() -> Self {
ParserState { ParserState {
@ -26,12 +31,12 @@ impl ParserState {
} }
} }
fn intern(&mut self, text: String) -> isize { fn intern(&mut self, text: &str) -> isize {
if let Some(u) = self.identifiers.get(&text) { if let Some(u) = self.identifiers.get(text) {
*u *u
} else { } else {
let unique = self.current_unique; let unique = self.current_unique;
self.identifiers.insert(text, unique); self.identifiers.insert(text.to_string(), unique);
self.current_unique += 1; self.current_unique += 1;
unique unique
} }
@ -39,10 +44,12 @@ impl ParserState {
} }
pub fn program(src: &str) -> anyhow::Result<Program> { pub fn program(src: &str) -> anyhow::Result<Program> {
let mut state = ParserState::new(); let mut parser = program_();
let mut parser = program_(&mut state);
let result = parser.easy_parse(position::Stream::new(src.trim())); let result = parser.parse(state::Stream {
stream: position::Stream::new(src.trim()),
state: ParserState::new(),
});
match result { match result {
Ok((program, _)) => Ok(program), Ok((program, _)) => Ok(program),
@ -50,20 +57,20 @@ pub fn program(src: &str) -> anyhow::Result<Program> {
} }
} }
fn program_<Input>(state: &mut ParserState) -> impl Parser<Input, Output = Program> fn program_<Input>() -> impl Parser<StateStream<Input>, Output = Program>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{ {
let prog = string("program").with(skip_many1(space())).with( let prog = string("program").with(skip_many1(space())).with(
(version(), skip_many1(space()), term(state).skip(spaces())) (version(), skip_many1(space()), term().skip(spaces()))
.map(|(version, _, term)| Program { version, term }), .map(|(version, _, term)| Program { version, term }),
); );
between(token('('), token(')'), prog).skip(spaces()) between(token('('), token(')'), prog).skip(spaces())
} }
fn version<Input>() -> impl Parser<Input, Output = (usize, usize, usize)> fn version<Input>() -> impl Parser<StateStream<Input>, Output = (usize, usize, usize)>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -86,31 +93,23 @@ where
) )
} }
fn term<Input>(state: &mut ParserState) -> impl Parser<Input, Output = Term> fn term<Input>() -> impl Parser<StateStream<Input>, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{ {
choice(( opaque!(no_partial(choice((
attempt(delay(state)), attempt(delay()),
attempt(lambda(state)), attempt(lambda()),
attempt(apply(state)), attempt(apply()),
attempt(constant()), attempt(constant()),
attempt(force(state)), attempt(force()),
attempt(error()), attempt(error()),
attempt(builtin()), attempt(builtin()),
)) ))))
} }
parser! { fn delay<Input>() -> impl Parser<StateStream<Input>, Output = Term>
fn term_[I](state: &mut ParserState)(I) -> Term
where [I: Stream<Token = char>]
{
term(state)
}
}
fn delay<Input>(state: &mut ParserState) -> impl Parser<Input, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -120,12 +119,12 @@ where
token(')'), token(')'),
string("delay") string("delay")
.with(skip_many1(space())) .with(skip_many1(space()))
.with(term_(state)) .with(term())
.map(|term| Term::Delay(Box::new(term))), .map(|term| Term::Delay(Box::new(term))),
) )
} }
fn force<Input>(state: &mut ParserState) -> impl Parser<Input, Output = Term> fn force<Input>() -> impl Parser<StateStream<Input>, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -135,12 +134,12 @@ where
token(')'), token(')'),
string("force") string("force")
.with(skip_many1(space())) .with(skip_many1(space()))
.with(term_(state)) .with(term())
.map(|term| Term::Force(Box::new(term))), .map(|term| Term::Force(Box::new(term))),
) )
} }
fn lambda<Input>(state: &mut ParserState) -> impl Parser<Input, Output = Term> fn lambda<Input>() -> impl Parser<StateStream<Input>, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -150,18 +149,20 @@ where
token(')'), token(')'),
string("lam") string("lam")
.with(skip_many1(space())) .with(skip_many1(space()))
.with((many1(alpha_num()), skip_many1(space()), term_(state))) .with((many1(alpha_num()), skip_many1(space()), term()))
.map(|(parameter_name, _, term)| Term::Lambda { .map_input(
|(parameter_name, _, term): (String, _, Term), input| Term::Lambda {
parameter_name: Name { parameter_name: Name {
unique: input.state.intern(&parameter_name),
text: parameter_name, text: parameter_name,
unique: state.intern(parameter_name),
}, },
body: Box::new(term), body: Box::new(term),
}), },
),
) )
} }
fn apply<Input>(state: &mut ParserState) -> impl Parser<Input, Output = Term> fn apply<Input>() -> impl Parser<StateStream<Input>, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -169,16 +170,14 @@ where
between( between(
token('['), token('['),
token(']'), token(']'),
(term_(state).skip(skip_many1(space())), term_(state)).map(|(function, argument)| { (term().skip(skip_many1(space())), term()).map(|(function, argument)| Term::Apply {
Term::Apply {
function: Box::new(function), function: Box::new(function),
argument: Box::new(argument), argument: Box::new(argument),
}
}), }),
) )
} }
pub fn builtin<Input>() -> impl Parser<Input, Output = Term> fn builtin<Input>() -> impl Parser<StateStream<Input>, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -195,7 +194,7 @@ where
) )
} }
pub fn error<Input>() -> impl Parser<Input, Output = Term> fn error<Input>() -> impl Parser<StateStream<Input>, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -209,7 +208,7 @@ where
) )
} }
pub fn constant<Input>() -> impl Parser<Input, Output = Term> fn constant<Input>() -> impl Parser<StateStream<Input>, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -230,7 +229,7 @@ where
) )
} }
fn constant_integer<Input>() -> impl Parser<Input, Output = Constant> fn constant_integer<Input>() -> impl Parser<StateStream<Input>, Output = Constant>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -241,7 +240,7 @@ where
.map(|d: String| Constant::Integer(d.parse::<isize>().unwrap())) .map(|d: String| Constant::Integer(d.parse::<isize>().unwrap()))
} }
fn constant_bytestring<Input>() -> impl Parser<Input, Output = Constant> fn constant_bytestring<Input>() -> impl Parser<StateStream<Input>, Output = Constant>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -253,7 +252,7 @@ where
.map(|b: String| Constant::ByteString(hex::decode(b).unwrap())) .map(|b: String| Constant::ByteString(hex::decode(b).unwrap()))
} }
fn constant_string<Input>() -> impl Parser<Input, Output = Constant> fn constant_string<Input>() -> impl Parser<StateStream<Input>, Output = Constant>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -264,7 +263,7 @@ where
.map(Constant::String) .map(Constant::String)
} }
fn constant_unit<Input>() -> impl Parser<Input, Output = Constant> fn constant_unit<Input>() -> impl Parser<StateStream<Input>, Output = Constant>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -275,7 +274,7 @@ where
.map(|_| Constant::Unit) .map(|_| Constant::Unit)
} }
fn constant_bool<Input>() -> impl Parser<Input, Output = Constant> fn constant_bool<Input>() -> impl Parser<StateStream<Input>, Output = Constant>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,