Skip to content

Commit e8b52ee

Browse files
committed
Merge from main to fix failing tests
2 parents 1ef2185 + c6e6067 commit e8b52ee

File tree

8 files changed

+135
-66
lines changed

8 files changed

+135
-66
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55

66
env:
77
CARGO_TERM_COLOR: always
8+
RUSTFLAGS: "-C link-arg=-fuse-ld=lld"
89

910
jobs:
1011
build:

cobalt-ast/src/intrinsics.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::*;
22
use once_cell::sync::Lazy;
3+
34
#[derive(Debug, Clone, Copy)]
45
pub struct ValueIntrinsic {
56
pub name: &'static str,
@@ -11,6 +12,7 @@ impl ValueIntrinsic {
1112
Self { name, wraps, ret }
1213
}
1314
}
15+
1416
#[derive(Debug, Clone, Copy)]
1517
pub struct FunctionIntrinsic {
1618
pub name: &'static str,
@@ -21,6 +23,7 @@ impl FunctionIntrinsic {
2123
Self { name, wraps }
2224
}
2325
}
26+
2427
type ValueCallType = for<'src, 'ctx> fn(ctx: &CompCtx<'src, 'ctx>) -> Value<'src, 'ctx>;
2528
type FunctionCallType = for<'src, 'ctx> fn(
2629
loc: SourceSpan,
@@ -31,6 +34,7 @@ type FunctionCallType = for<'src, 'ctx> fn(
3134

3235
inventory::collect!(ValueIntrinsic);
3336
inventory::collect!(FunctionIntrinsic);
37+
3438
pub static VALUE_INTRINSICS: Lazy<flurry::HashMap<&'static str, ValueIntrinsic>> =
3539
Lazy::new(|| {
3640
inventory::iter::<ValueIntrinsic>()
@@ -43,6 +47,7 @@ pub static FUNCTION_INTRINSICS: Lazy<flurry::HashMap<&'static str, FunctionIntri
4347
.map(|&i| (i.name, i))
4448
.collect()
4549
});
50+
4651
pub mod misc;
4752
pub mod types;
4853
pub mod version;

cobalt-cli/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,13 @@ pub fn driver(cli: Cli) -> anyhow::Result<()> {
458458
let mut ast = ast.unwrap_or_default();
459459
ast.file = Some(file);
460460
for err in errs {
461-
eprintln!("{:?}", Report::from(err).with_source_code(file));
461+
let err = err.with_file(file);
462+
if let Err(e2) =
463+
writeln!(std::io::stderr(), "{:?}", Report::from(err.clone()))
464+
{
465+
error!("\nan error occured printing to stdout: {e2}");
466+
eprintln!("original diagnostic: {err}");
467+
}
462468
}
463469
if locs {
464470
print!("({} nodes)\n{ast:#}", ast.nodes())

cobalt-cli/src/main.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ fn main() {
44
match err.downcast() {
55
Ok(Exit(code)) => std::process::exit(code),
66
Err(err) => {
7-
cobalt_errors::error!("{err:#}");
7+
if let Err(e2) = cobalt_errors::try_error!("{err:#}") {
8+
eprintln!("error encountered printing error: {e2}");
9+
eprintln!("original error (debug): {err:#?}");
10+
}
811
std::process::exit(101);
912
}
1013
}

cobalt-errors/src/color.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,32 @@ macro_rules! warning {
2424
writeln!(stderr, $($toks)*).unwrap();
2525
}}
2626
}
27+
28+
#[macro_export]
29+
macro_rules! try_error {
30+
($($toks:tt)*) => {(|| {
31+
use std::io::Write;
32+
use termcolor::{StandardStream, ColorChoice, ColorSpec, Color, WriteColor};
33+
let mut stderr = StandardStream::stderr(ColorChoice::Auto);
34+
stderr.set_color(&ColorSpec::new().set_fg(Some(Color::Red)).set_bold(true))?;
35+
write!(stderr, "error")?;
36+
stderr.reset()?;
37+
write!(stderr, ": ")?;
38+
writeln!(stderr, $($toks)*)?;
39+
std::io::Result::Ok(())
40+
})()}
41+
}
42+
#[macro_export]
43+
macro_rules! try_warning {
44+
($($toks:tt)*) => {(|| {
45+
use std::io::Write;
46+
use termcolor::{StandardStream, ColorChoice, ColorSpec, Color, WriteColor};
47+
let mut stderr = StandardStream::stderr(ColorChoice::Auto);
48+
stderr.set_color(&ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true))?;
49+
write!(stderr, "warning")?;
50+
stderr.reset()?;
51+
write!(stderr, ": ")?;
52+
writeln!(stderr, $($toks)*)?;
53+
std::io::Result::Ok(())
54+
})()}
55+
}

cobalt-parser/src/lexer/mod.rs

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,29 @@
1-
use std::str::CharIndices;
2-
31
use cobalt_errors::SourceSpan;
42

53
pub mod tokenizer;
64
pub mod tokens;
75

86
pub struct SourceReader<'src> {
97
pub source: &'src str,
10-
/// Calling `next()` will give us the index of the character returned, but
11-
/// since we actually want the index of the *next* character, this should
12-
/// be one character ahead. This also means we don't need the iterator itself
13-
/// to be peekable.
14-
iter: CharIndices<'src>,
15-
next_char: Option<char>,
168
/// The index of the next character to be returned.
179
pub index: usize,
1810
}
1911

2012
impl<'src> SourceReader<'src> {
2113
pub fn new(source: &'src str) -> SourceReader<'src> {
22-
let mut iter = source.char_indices();
23-
let next = iter.next();
24-
let next_char = next.map(|next| next.1);
25-
26-
SourceReader {
27-
source,
28-
iter,
29-
next_char,
30-
index: 0,
31-
}
14+
SourceReader { source, index: 0 }
3215
}
3316

3417
pub fn next_char(&mut self) -> Option<char> {
35-
let to_return = self.next_char;
18+
let to_ret = self.source[self.index..].chars().next();
3619

37-
let iter_next = self.iter.next();
38-
if let Some(next) = iter_next {
39-
self.index = next.0;
40-
self.next_char = Some(next.1);
41-
} else {
42-
self.index = self.source.len();
43-
self.next_char = None
44-
}
20+
self.index += to_ret.map_or(0, char::len_utf8);
4521

46-
to_return
22+
to_ret
4723
}
4824

49-
pub fn peek(&mut self) -> Option<&char> {
50-
self.next_char.as_ref()
25+
pub fn peek(&mut self) -> Option<char> {
26+
self.source[self.index..].chars().next()
5127
}
5228

5329
/// Returns the slice `self.source[(index - offset)..index]`.

cobalt-parser/src/lexer/tokenizer.rs

Lines changed: 67 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl<'src> SourceReader<'src> {
8484
let mut tokens = Vec::new();
8585
let mut errors = Vec::new();
8686

87-
while let Some(&c) = self.peek() {
87+
while let Some(c) = self.peek() {
8888
match c {
8989
' ' | '\r' | '\n' | '\t' => {
9090
self.next_char();
@@ -133,11 +133,11 @@ impl<'src> SourceReader<'src> {
133133
}
134134
continue;
135135
}
136-
Some(&c) => {
136+
Some(c) => {
137137
if is_ident_start(c) {
138138
loop {
139139
self.next_char();
140-
let Some(&c) = self.peek() else { break };
140+
let Some(c) = self.peek() else { break };
141141
if !is_xid_continue(c) {
142142
break;
143143
}
@@ -491,9 +491,9 @@ impl<'src> SourceReader<'src> {
491491

492492
self.next_char();
493493
let (base, alt) = match self.peek() {
494-
Some(&'x') => (16, true),
495-
Some(&'o') => (8, true),
496-
Some(&'b') => (2, true),
494+
Some('x') => (16, true),
495+
Some('o') => (8, true),
496+
Some('b') => (2, true),
497497
_ => (10, false),
498498
};
499499
if alt {
@@ -502,7 +502,7 @@ impl<'src> SourceReader<'src> {
502502

503503
// Now pointing to the first digit.
504504
let mut end = self.index;
505-
while let Some(&ch) = self.peek() {
505+
while let Some(ch) = self.peek() {
506506
if ch.is_digit(base as _) {
507507
self.next_char();
508508
end += 1;
@@ -513,7 +513,7 @@ impl<'src> SourceReader<'src> {
513513
base,
514514
loc: (self.index, 1).into(),
515515
});
516-
while self.peek().map_or(false, char::is_ascii_digit) {
516+
while self.peek().map_or(false, |c| c.is_ascii_digit()) {
517517
self.next_char();
518518
}
519519
}
@@ -523,9 +523,27 @@ impl<'src> SourceReader<'src> {
523523

524524
// Now pointing to the last digit before the non-digit.
525525

526-
if !alt && self.peek() == Some(&'.') {
527-
self.next_char();
528-
end += 1;
526+
if !alt && self.peek() == Some('.') {
527+
let idx = self.index;
528+
if loop {
529+
match self.next_char() {
530+
Some('_' | '@') => break true,
531+
Some(c) if is_xid_start(c) => break true,
532+
Some(c) if !c.is_whitespace() => break false,
533+
_ => {}
534+
}
535+
} {
536+
self.index = idx;
537+
tokens.push(Token {
538+
kind: TokenKind::Literal(LiteralToken::Int(
539+
&self.source[start..end],
540+
)),
541+
span: (start..end).into(),
542+
});
543+
continue;
544+
} else {
545+
end += 1;
546+
}
529547
} else {
530548
// Not a float.
531549
tokens.push(Token {
@@ -572,9 +590,34 @@ impl<'src> SourceReader<'src> {
572590

573591
// Now pointing to the last digit before the non-digit.
574592

575-
if self.peek() == Some(&'.') {
593+
if self.peek() == Some('.') {
594+
let idx = self.index;
576595
self.next_char();
577-
num_len += 1;
596+
let old_len = num_len;
597+
// num_len += 1;
598+
if loop {
599+
match {
600+
let ch = self.next_char();
601+
num_len += ch.map_or(0, |c| c.len_utf8());
602+
ch
603+
} {
604+
Some('_' | '@') => break true,
605+
Some(c) if is_xid_start(c) => break true,
606+
Some(c) if !c.is_whitespace() => break false,
607+
None => break false,
608+
_ => {}
609+
}
610+
} {
611+
self.index = idx;
612+
tokens.push(Token {
613+
kind: TokenKind::Literal(LiteralToken::Int(
614+
self.slice_backward(old_len),
615+
)),
616+
span: self.source_span_backward(old_len),
617+
});
618+
continue;
619+
}
620+
self.index = idx + 1;
578621
} else {
579622
// Not a float.
580623
tokens.push(Token {
@@ -618,14 +661,14 @@ impl<'src> SourceReader<'src> {
618661
self.next_char();
619662

620663
match self.peek() {
621-
Some(&'?') => {
664+
Some('?') => {
622665
self.next_char();
623666
tokens.push(Token {
624667
kind: TokenKind::BinOp(BinOpToken::Colonq),
625668
span: self.source_span_backward(2),
626669
});
627670
}
628-
Some(&':') => {
671+
Some(':') => {
629672
self.next_char();
630673
tokens.push(Token {
631674
kind: TokenKind::ColonColon,
@@ -659,7 +702,7 @@ impl<'src> SourceReader<'src> {
659702
let span_start = self.index;
660703
self.next_char();
661704

662-
if let Some(&c) = self.peek() {
705+
if let Some(c) = self.peek() {
663706
if !is_ident_start(c) {
664707
errors.push(CobaltError::ExpectedFound {
665708
ex: "start of identifier",
@@ -704,7 +747,7 @@ impl<'src> SourceReader<'src> {
704747
// --- Optional param.
705748

706749
match self.peek() {
707-
Some(&'(') => {}
750+
Some('(') => {}
708751
_ => {
709752
tokens.push(Token {
710753
kind: TokenKind::Annotation((name, None)),
@@ -718,7 +761,7 @@ impl<'src> SourceReader<'src> {
718761
}
719762

720763
// Eat the '('.
721-
assert_eq!(self.peek(), Some(&'('));
764+
assert_eq!(self.peek(), Some('('));
722765
self.next_char();
723766

724767
let arg_span_start = self.index;
@@ -777,13 +820,13 @@ impl<'src> SourceReader<'src> {
777820
}
778821
let c = c.unwrap();
779822

780-
if c == &'\\' {
823+
if c == '\\' {
781824
last_was_escape = !last_was_escape;
782825
self.next_char();
783826
continue;
784827
}
785828

786-
if c == &'\'' && !last_was_escape {
829+
if c == '\'' && !last_was_escape {
787830
break;
788831
}
789832

@@ -834,7 +877,7 @@ impl<'src> SourceReader<'src> {
834877
fn eat_ident(&mut self) -> Result<Token<'src>, CobaltError<'src>> {
835878
let start_idx = self.index;
836879

837-
if let Some(&c) = self.peek() {
880+
if let Some(c) = self.peek() {
838881
if !(is_xid_start(c) || c == '_') {
839882
self.next_char();
840883
let err = CobaltError::ExpectedFound {
@@ -858,7 +901,7 @@ impl<'src> SourceReader<'src> {
858901
// The reader is now pointing at the first character of the identifier.
859902

860903
while let Some(c) = self.peek() {
861-
if !is_xid_continue(*c) {
904+
if !is_xid_continue(c) {
862905
break;
863906
}
864907

@@ -940,13 +983,13 @@ impl<'src> SourceReader<'src> {
940983
}
941984
let c = c.unwrap();
942985

943-
if c == &'\\' {
986+
if c == '\\' {
944987
last_was_escape = !last_was_escape;
945988
self.next_char();
946989
continue;
947990
}
948991

949-
if c == &'"' && !last_was_escape {
992+
if c == '"' && !last_was_escape {
950993
break;
951994
}
952995

0 commit comments

Comments
 (0)