mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Several migration fixes and make some zig parser improvements based on migrated code in the wild (#7716)
This commit is contained in:
parent
68af4b9a06
commit
6d22c4dd7c
329 changed files with 1663 additions and 833 deletions
|
@ -9,6 +9,7 @@ use roc_can::expr::{DeclarationTag, Declarations, Expr};
|
|||
use roc_error_macros::{internal_error, user_error};
|
||||
use roc_fmt::def::fmt_defs;
|
||||
use roc_fmt::header::fmt_header;
|
||||
use roc_fmt::migrate::MigrateError;
|
||||
use roc_fmt::Buf;
|
||||
use roc_fmt::MigrationFlags;
|
||||
use roc_load::{ExecutionMode, FunctionKind, LoadConfig, LoadedModule, LoadingProblem, Threading};
|
||||
|
@ -78,7 +79,7 @@ fn is_roc_file(path: &Path) -> bool {
|
|||
pub fn format_files(
|
||||
files: std::vec::Vec<PathBuf>,
|
||||
mode: FormatMode,
|
||||
flags: MigrationFlags,
|
||||
migrate: bool,
|
||||
) -> Result<(), String> {
|
||||
let arena = Bump::new();
|
||||
let mut files_to_reformat = Vec::new(); // to track which files failed `roc format --check`
|
||||
|
@ -86,7 +87,7 @@ pub fn format_files(
|
|||
for file in flatten_directories(files) {
|
||||
let src = std::fs::read_to_string(&file).unwrap();
|
||||
|
||||
match format_src(&arena, &src, flags) {
|
||||
match format_src(&arena, &src, migrate) {
|
||||
Ok(buf) => {
|
||||
match mode {
|
||||
FormatMode::CheckOnly => {
|
||||
|
@ -168,6 +169,11 @@ pub fn format_files(
|
|||
unstable_2_file.display()
|
||||
);
|
||||
}
|
||||
FormatProblem::UnsupportedMigration(e) => internal_error!(
|
||||
"Formatting bug; unsupported migration\n\n\
|
||||
Migration error was: {:?}\n\n",
|
||||
e
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -197,13 +203,28 @@ pub enum FormatProblem {
|
|||
formatted_src: String,
|
||||
reformatted_src: String,
|
||||
},
|
||||
UnsupportedMigration(MigrateError),
|
||||
}
|
||||
|
||||
pub fn format_src(arena: &Bump, src: &str, flags: MigrationFlags) -> Result<String, FormatProblem> {
|
||||
pub fn format_src(arena: &Bump, src: &str, migrate: bool) -> Result<String, FormatProblem> {
|
||||
let ast = arena.alloc(parse_all(arena, src).unwrap_or_else(|e| {
|
||||
user_error!("Unexpected parse failure when parsing this formatting:\n\n{src}\n\nParse error was:\n\n{:#?}\n\n", e)
|
||||
}));
|
||||
let flags = MigrationFlags {
|
||||
snakify: migrate,
|
||||
parens_and_commas: migrate,
|
||||
};
|
||||
let mut buf = Buf::new_in(arena, flags);
|
||||
|
||||
if migrate {
|
||||
roc_fmt::migrate::fmt_header(&mut buf, &ast.header)
|
||||
.map_err(FormatProblem::UnsupportedMigration)?;
|
||||
roc_fmt::migrate::fmt_defs(&mut buf, &ast.defs)
|
||||
.map_err(FormatProblem::UnsupportedMigration)?;
|
||||
buf.fmt_end_of_file();
|
||||
return Ok(buf.as_str().to_string());
|
||||
}
|
||||
|
||||
fmt_all(&mut buf, ast);
|
||||
|
||||
let reparsed_ast = match arena.alloc(parse_all(arena, buf.as_str())) {
|
||||
|
@ -224,9 +245,7 @@ pub fn format_src(arena: &Bump, src: &str, flags: MigrationFlags) -> Result<Stri
|
|||
// the PartialEq implementation is returning `false` even when the Debug-formatted impl is exactly the same.
|
||||
// I don't have the patience to debug this right now, so let's leave it for another day...
|
||||
// TODO: fix PartialEq impl on ast types
|
||||
if !flags.at_least_one_active()
|
||||
&& format!("{ast_normalized:?}") != format!("{reparsed_ast_normalized:?}")
|
||||
{
|
||||
if format!("{ast_normalized:?}") != format!("{reparsed_ast_normalized:?}") {
|
||||
return Err(FormatProblem::ReformattingChangedAst {
|
||||
formatted_src: buf.as_str().to_string(),
|
||||
ast_before: format!("{ast_normalized:#?}\n"),
|
||||
|
@ -235,7 +254,7 @@ pub fn format_src(arena: &Bump, src: &str, flags: MigrationFlags) -> Result<Stri
|
|||
}
|
||||
|
||||
// Now verify that the resultant formatting is _stable_ - i.e. that it doesn't change again if re-formatted
|
||||
let mut reformatted_buf = Buf::new_in(arena, flags);
|
||||
let mut reformatted_buf = Buf::new_in(arena, MigrationFlags::default());
|
||||
|
||||
fmt_all(&mut reformatted_buf, reparsed_ast);
|
||||
|
||||
|
@ -483,12 +502,7 @@ main =
|
|||
fn test_single_file_needs_reformatting() {
|
||||
let dir = tempdir().unwrap();
|
||||
let file_path = setup_test_file(dir.path(), "test1.roc", UNFORMATTED_ROC);
|
||||
let flags = MigrationFlags {
|
||||
snakify: false,
|
||||
parens_and_commas: false,
|
||||
};
|
||||
|
||||
let result = format_files(vec![file_path.clone()], FormatMode::CheckOnly, flags);
|
||||
let result = format_files(vec![file_path.clone()], FormatMode::CheckOnly, false);
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.unwrap_err(),
|
||||
|
@ -506,12 +520,7 @@ main =
|
|||
let dir = tempdir().unwrap();
|
||||
let file1 = setup_test_file(dir.path(), "test1.roc", UNFORMATTED_ROC);
|
||||
let file2 = setup_test_file(dir.path(), "test2.roc", UNFORMATTED_ROC);
|
||||
let flags = MigrationFlags {
|
||||
snakify: false,
|
||||
parens_and_commas: false,
|
||||
};
|
||||
|
||||
let result = format_files(vec![file1, file2], FormatMode::CheckOnly, flags);
|
||||
let result = format_files(vec![file1, file2], FormatMode::CheckOnly, false);
|
||||
assert!(result.is_err());
|
||||
let error_message = result.unwrap_err();
|
||||
assert!(error_message.contains("test1.roc") && error_message.contains("test2.roc"));
|
||||
|
@ -523,12 +532,7 @@ main =
|
|||
fn test_no_files_need_reformatting() {
|
||||
let dir = tempdir().unwrap();
|
||||
let file_path = setup_test_file(dir.path(), "formatted.roc", FORMATTED_ROC);
|
||||
let flags = MigrationFlags {
|
||||
snakify: false,
|
||||
parens_and_commas: false,
|
||||
};
|
||||
|
||||
let result = format_files(vec![file_path], FormatMode::CheckOnly, flags);
|
||||
let result = format_files(vec![file_path], FormatMode::CheckOnly, false);
|
||||
assert!(result.is_ok());
|
||||
|
||||
cleanup_temp_dir(dir);
|
||||
|
@ -540,15 +544,10 @@ main =
|
|||
let file_formatted = setup_test_file(dir.path(), "formatted.roc", FORMATTED_ROC);
|
||||
let file1_unformated = setup_test_file(dir.path(), "test1.roc", UNFORMATTED_ROC);
|
||||
let file2_unformated = setup_test_file(dir.path(), "test2.roc", UNFORMATTED_ROC);
|
||||
let flags = MigrationFlags {
|
||||
snakify: false,
|
||||
parens_and_commas: false,
|
||||
};
|
||||
|
||||
let result = format_files(
|
||||
vec![file_formatted, file1_unformated, file2_unformated],
|
||||
FormatMode::CheckOnly,
|
||||
flags,
|
||||
false,
|
||||
);
|
||||
assert!(result.is_err());
|
||||
let error_message = result.unwrap_err();
|
||||
|
|
|
@ -13,7 +13,6 @@ use roc_cli::{
|
|||
};
|
||||
use roc_docs::generate_docs_html;
|
||||
use roc_error_macros::{internal_error, user_error};
|
||||
use roc_fmt::MigrationFlags;
|
||||
use roc_gen_dev::AssemblyBackendMode;
|
||||
use roc_gen_llvm::llvm::build::LlvmBackendMode;
|
||||
use roc_load::{LoadingProblem, Threading};
|
||||
|
@ -395,10 +394,6 @@ fn main() -> io::Result<()> {
|
|||
false => FormatMode::WriteToFile,
|
||||
}
|
||||
};
|
||||
let flags = MigrationFlags {
|
||||
snakify: migrate,
|
||||
parens_and_commas: migrate,
|
||||
};
|
||||
|
||||
if from_stdin && matches!(format_mode, FormatMode::WriteToFile) {
|
||||
eprintln!("When using the --stdin flag, either the --check or the --stdout flag must also be specified. (Otherwise, it's unclear what filename to write to!)");
|
||||
|
@ -451,7 +446,7 @@ fn main() -> io::Result<()> {
|
|||
std::process::exit(1);
|
||||
});
|
||||
|
||||
match format_src(&arena, src, flags) {
|
||||
match format_src(&arena, src, migrate) {
|
||||
Ok(formatted_src) => {
|
||||
match format_mode {
|
||||
FormatMode::CheckOnly => {
|
||||
|
@ -483,7 +478,7 @@ fn main() -> io::Result<()> {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
match format_files(roc_files, format_mode, flags) {
|
||||
match format_files(roc_files, format_mode, migrate) {
|
||||
Ok(()) => 0,
|
||||
Err(message) => {
|
||||
eprintln!("{message}");
|
||||
|
|
|
@ -24,7 +24,7 @@ pub struct Buf<'a> {
|
|||
flags: MigrationFlags,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub struct MigrationFlags {
|
||||
pub snakify: bool,
|
||||
pub parens_and_commas: bool,
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use roc_module::called_via::UnaryOp;
|
||||
use bumpalo::collections::String;
|
||||
use bumpalo::Bump;
|
||||
use roc_module::called_via::{Associativity, BinOp, UnaryOp};
|
||||
use roc_parse::{
|
||||
ast::{
|
||||
AbilityImpls, AssignedField, Base, Collection, Defs, Expr, FunctionArrow, Header,
|
||||
ImplementsAbilities, ImplementsAbility, ImplementsClause, ImportAlias, ImportAsKeyword,
|
||||
ImportExposingKeyword, ImportedModuleName, IngestedFileAnnotation, IngestedFileImport,
|
||||
ModuleImport, ModuleImportParams, Pattern, Spaced, Spaces, SpacesBefore, Tag,
|
||||
TypeAnnotation, TypeDef, TypeHeader, TypeVar, ValueDef,
|
||||
AbilityImpls, AssignedField, Base, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces,
|
||||
FunctionArrow, Header, ImplementsAbilities, ImplementsAbility, ImplementsClause,
|
||||
ImportAlias, ImportAsKeyword, ImportExposingKeyword, ImportedModuleName,
|
||||
IngestedFileAnnotation, IngestedFileImport, ModuleImport, ModuleImportParams, Pattern,
|
||||
Spaced, Spaces, SpacesBefore, Tag, TypeAnnotation, TypeDef, TypeHeader, TypeVar, ValueDef,
|
||||
},
|
||||
header::{
|
||||
AppHeader, ExposedName, HostedHeader, Keyword, KeywordItem, ModuleHeader, ModuleName,
|
||||
|
@ -25,7 +27,7 @@ use crate::{
|
|||
},
|
||||
pattern::snakify_camel_ident,
|
||||
spaces::fmt_spaces,
|
||||
Buf,
|
||||
Buf, MigrationFlags,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -76,7 +78,7 @@ impl<F: Fmt> Fmt for AssignedField<'_, F> {
|
|||
buf.indent(indent);
|
||||
buf.push_str(":");
|
||||
buf.spaces(1);
|
||||
loc1.fmt(buf, indent, Suffix::None)?;
|
||||
loc1.fmt(buf, indent, suffix)?;
|
||||
}
|
||||
AssignedField::OptionalValue(name, comment_or_newlines, loc1) => {
|
||||
buf.indent(indent);
|
||||
|
@ -87,7 +89,7 @@ impl<F: Fmt> Fmt for AssignedField<'_, F> {
|
|||
buf.indent(indent);
|
||||
buf.push_str(":");
|
||||
buf.spaces(1);
|
||||
loc1.fmt(buf, indent, Suffix::None)?;
|
||||
loc1.fmt(buf, indent, suffix)?;
|
||||
}
|
||||
AssignedField::IgnoredValue(name, comment_or_newlines, loc1) => {
|
||||
buf.indent(indent);
|
||||
|
@ -99,7 +101,7 @@ impl<F: Fmt> Fmt for AssignedField<'_, F> {
|
|||
buf.indent(indent);
|
||||
buf.push_str(":");
|
||||
buf.spaces(1);
|
||||
loc1.fmt(buf, indent, Suffix::None)?;
|
||||
loc1.fmt(buf, indent, suffix)?;
|
||||
}
|
||||
AssignedField::LabelOnly(name) => {
|
||||
buf.indent(indent);
|
||||
|
@ -127,13 +129,13 @@ pub fn fmt_pattern(
|
|||
match pat {
|
||||
Pattern::Identifier { ident } => {
|
||||
buf.indent(indent);
|
||||
buf.push_str(ident);
|
||||
snakify_camel_ident(buf, ident);
|
||||
}
|
||||
Pattern::QualifiedIdentifier { module_name, ident } => {
|
||||
buf.indent(indent);
|
||||
buf.push_str(module_name);
|
||||
buf.push('.');
|
||||
buf.push_str(ident);
|
||||
snakify_camel_ident(buf, ident);
|
||||
}
|
||||
Pattern::Tag(tag) => {
|
||||
buf.indent(indent);
|
||||
|
@ -145,16 +147,31 @@ pub fn fmt_pattern(
|
|||
}
|
||||
Pattern::Apply(loc, locs) => {
|
||||
fmt_pattern(buf, indent, &loc.value, Suffix::OpenRound)?;
|
||||
for loc in locs.iter() {
|
||||
fmt_pattern(buf, indent, &loc.value, Suffix::Comma)?;
|
||||
for (i, loc) in locs.iter().enumerate() {
|
||||
let is_last = i == locs.len() - 1;
|
||||
fmt_pattern(
|
||||
buf,
|
||||
indent,
|
||||
&loc.value,
|
||||
if is_last { Suffix::None } else { Suffix::Comma },
|
||||
)?;
|
||||
}
|
||||
buf.indent(indent);
|
||||
buf.push(')');
|
||||
}
|
||||
Pattern::PncApply(loc, collection) => {
|
||||
fmt_pattern(buf, indent, &loc.value, Suffix::OpenRound)?;
|
||||
for loc in collection.iter() {
|
||||
fmt_pattern(buf, indent, &loc.value, Suffix::Comma)?;
|
||||
for (i, loc) in collection.iter().enumerate() {
|
||||
let is_last = i == collection.len() - 1;
|
||||
fmt_pattern(
|
||||
buf,
|
||||
indent,
|
||||
&loc.value,
|
||||
if is_last { Suffix::None } else { Suffix::Comma },
|
||||
)?;
|
||||
if !is_last {
|
||||
buf.spaces(1);
|
||||
}
|
||||
}
|
||||
if !collection.final_comments().is_empty() {
|
||||
fmt_spaces(buf, collection.final_comments().iter(), indent);
|
||||
|
@ -325,11 +342,7 @@ pub fn fmt_expr(
|
|||
buf.push_str(module_name);
|
||||
buf.push('.');
|
||||
}
|
||||
if buf.flags().snakify {
|
||||
snakify_camel_ident(buf, ident);
|
||||
} else {
|
||||
buf.push_str(ident);
|
||||
}
|
||||
}
|
||||
Expr::Underscore(name) => {
|
||||
buf.indent(indent);
|
||||
|
@ -465,18 +478,34 @@ pub fn fmt_expr(
|
|||
Expr::LowLevelDbg(..) => todo!(),
|
||||
Expr::Apply(func, args, _) => {
|
||||
fmt_expr(buf, indent, &func.value, Suffix::OpenRound)?;
|
||||
for arg in *args {
|
||||
// TODO: make the suffix depend on whether we're multiline
|
||||
fmt_expr(buf, indent, &arg.value, Suffix::Comma)?;
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
let is_last = i == args.len() - 1;
|
||||
fmt_expr(
|
||||
buf,
|
||||
indent,
|
||||
&arg.value,
|
||||
if is_last { Suffix::None } else { Suffix::Comma },
|
||||
)?;
|
||||
if !is_last {
|
||||
buf.spaces(1);
|
||||
}
|
||||
}
|
||||
buf.indent(indent);
|
||||
buf.push(')');
|
||||
}
|
||||
Expr::PncApply(func, collection) => {
|
||||
fmt_expr(buf, indent, &func.value, Suffix::OpenRound)?;
|
||||
for arg in collection.iter() {
|
||||
// TODO: make the suffix depend on whether we're multiline
|
||||
fmt_expr(buf, indent, &arg.value, Suffix::Comma)?;
|
||||
for (i, arg) in collection.iter().enumerate() {
|
||||
let is_last = i == collection.len() - 1;
|
||||
fmt_expr(
|
||||
buf,
|
||||
indent,
|
||||
&arg.value,
|
||||
if is_last { Suffix::None } else { Suffix::Comma },
|
||||
)?;
|
||||
if !is_last {
|
||||
buf.spaces(1);
|
||||
}
|
||||
}
|
||||
if !collection.final_comments().is_empty() {
|
||||
fmt_spaces(buf, collection.final_comments().iter(), indent);
|
||||
|
@ -485,14 +514,9 @@ pub fn fmt_expr(
|
|||
buf.push(')');
|
||||
}
|
||||
Expr::BinOps(expr_op_pairs, last_expr) => {
|
||||
for (expr, op) in *expr_op_pairs {
|
||||
fmt_expr(buf, indent, &expr.value, Suffix::None)?;
|
||||
buf.spaces(1);
|
||||
buf.indent(indent);
|
||||
push_op(buf, op.value);
|
||||
buf.spaces(1);
|
||||
}
|
||||
fmt_expr(buf, indent, &last_expr.value, Suffix::None)?;
|
||||
let arena = buf.text.bump();
|
||||
let converted = migrate_pizza(buf, arena, expr_op_pairs, **last_expr)?;
|
||||
fmt_converted_ops(buf, indent, &converted, Suffix::None)?;
|
||||
}
|
||||
Expr::UnaryOp(expr, op) => {
|
||||
buf.indent(indent);
|
||||
|
@ -528,10 +552,11 @@ pub fn fmt_expr(
|
|||
}
|
||||
Expr::When(cond, when_branchs) => {
|
||||
buf.indent(indent);
|
||||
buf.push_str("when");
|
||||
buf.push_str("match");
|
||||
buf.spaces(1);
|
||||
fmt_expr(buf, indent, &cond.value, Suffix::None)?;
|
||||
buf.indent(indent);
|
||||
buf.spaces(1);
|
||||
buf.push('{');
|
||||
buf.ensure_ends_with_newline();
|
||||
for branch in when_branchs.iter() {
|
||||
|
@ -599,6 +624,447 @@ pub fn fmt_expr(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum MigratedBinOp<'a> {
|
||||
BinOp {
|
||||
lhs: &'a MigratedBinOp<'a>,
|
||||
op: BinOp,
|
||||
rhs: &'a MigratedBinOp<'a>,
|
||||
},
|
||||
Parens(&'a MigratedBinOp<'a>),
|
||||
StaticDispatch {
|
||||
lhs: &'a MigratedBinOp<'a>,
|
||||
before: &'a [CommentOrNewline<'a>],
|
||||
func: &'a str,
|
||||
args: &'a [Expr<'a>],
|
||||
after: &'a [CommentOrNewline<'a>],
|
||||
},
|
||||
FuncStaticDispatch {
|
||||
lhs: &'a MigratedBinOp<'a>,
|
||||
before: &'a [CommentOrNewline<'a>],
|
||||
func: &'a Expr<'a>,
|
||||
args: &'a [Expr<'a>],
|
||||
after: &'a [CommentOrNewline<'a>],
|
||||
},
|
||||
Expr(Expr<'a>),
|
||||
}
|
||||
|
||||
fn apply_ops<'a>(
|
||||
buf: &Buf<'a>,
|
||||
arena: &'a Bump,
|
||||
stack: &mut Vec<MigratedBinOp<'a>>,
|
||||
ops: &mut Vec<BinOp>,
|
||||
min_precedence: u8,
|
||||
) -> Result<(), MigrateError> {
|
||||
while let Some(&op) = ops.last() {
|
||||
if op.precedence() <= min_precedence
|
||||
&& (op.associativity() == Associativity::RightAssociative
|
||||
|| op.precedence() < min_precedence)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ops.pop();
|
||||
|
||||
let rhs = stack.pop().unwrap();
|
||||
let lhs = stack.pop().unwrap();
|
||||
|
||||
let result = match op {
|
||||
BinOp::Pizza => {
|
||||
// Need to migrate to StaticDispatch or FuncStaticDispatch!
|
||||
match rhs {
|
||||
MigratedBinOp::Expr(expr) => {
|
||||
let expr = expr.extract_spaces();
|
||||
match expr.item {
|
||||
Expr::Apply(func, args, _) => {
|
||||
if let Some(name) = is_staticable(buf, &func.value) {
|
||||
MigratedBinOp::StaticDispatch {
|
||||
lhs: maybe_parens(arena, lhs),
|
||||
before: expr.before,
|
||||
func: arena.alloc_str(name),
|
||||
args: arena.alloc_slice_fill_iter(
|
||||
args.iter().map(|arg| arg.value),
|
||||
),
|
||||
after: expr.after,
|
||||
}
|
||||
} else {
|
||||
MigratedBinOp::FuncStaticDispatch {
|
||||
lhs: maybe_parens(arena, lhs),
|
||||
before: expr.before,
|
||||
func: arena.alloc(func.value),
|
||||
args: arena.alloc_slice_fill_iter(
|
||||
args.iter().map(|arg| arg.value),
|
||||
),
|
||||
after: expr.after,
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::Var { module_name, ident } => {
|
||||
let ident = if buf.flags.snakify {
|
||||
snakify_camel_ident_in_bump(buf.text.bump(), ident)
|
||||
.into_bump_str()
|
||||
} else {
|
||||
ident
|
||||
};
|
||||
if is_static_method(module_name, ident) {
|
||||
MigratedBinOp::StaticDispatch {
|
||||
lhs: maybe_parens(arena, lhs),
|
||||
before: expr.before,
|
||||
func: arena.alloc_str(ident),
|
||||
args: &[],
|
||||
after: expr.after,
|
||||
}
|
||||
} else {
|
||||
MigratedBinOp::FuncStaticDispatch {
|
||||
lhs: maybe_parens(arena, lhs),
|
||||
before: expr.before,
|
||||
func: arena.alloc(Expr::Var { module_name, ident }),
|
||||
args: &[],
|
||||
after: expr.after,
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return Err(MigrateError::PizzaOpRhsNotSupported),
|
||||
}
|
||||
}
|
||||
_ => return Err(MigrateError::PizzaOpRhsNotSupported),
|
||||
}
|
||||
}
|
||||
_ => MigratedBinOp::BinOp {
|
||||
lhs: arena.alloc(lhs),
|
||||
op,
|
||||
rhs: arena.alloc(rhs),
|
||||
},
|
||||
};
|
||||
|
||||
stack.push(result);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn maybe_parens<'a>(arena: &'a Bump, lhs: MigratedBinOp<'a>) -> &'a MigratedBinOp<'a> {
|
||||
match lhs {
|
||||
MigratedBinOp::Parens(_)
|
||||
| MigratedBinOp::StaticDispatch { .. }
|
||||
| MigratedBinOp::FuncStaticDispatch { .. }
|
||||
| MigratedBinOp::Expr(_) => arena.alloc(lhs),
|
||||
MigratedBinOp::BinOp { .. } => arena.alloc(MigratedBinOp::Parens(arena.alloc(lhs))),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_staticable<'a>(buf: &Buf<'a>, value: &Expr<'a>) -> Option<&'a str> {
|
||||
match value {
|
||||
Expr::Var { module_name, ident } => {
|
||||
let ident = if buf.flags.snakify {
|
||||
snakify_camel_ident_in_bump(buf.text.bump(), ident).into_bump_str()
|
||||
} else {
|
||||
ident
|
||||
};
|
||||
if is_static_method(module_name, ident) {
|
||||
Some(ident)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_static_method(module_name: &str, ident: &str) -> bool {
|
||||
match module_name {
|
||||
"Str" => matches!(
|
||||
ident,
|
||||
"concat"
|
||||
| "is_empty"
|
||||
| "join_with"
|
||||
| "split_on"
|
||||
| "repeat"
|
||||
| "count_utf8_bytes"
|
||||
| "to_utf8"
|
||||
| "starts_with"
|
||||
| "ends_with"
|
||||
| "trim"
|
||||
| "trim_start"
|
||||
| "trim_end"
|
||||
| "to_dec"
|
||||
| "to_f64"
|
||||
| "to_f32"
|
||||
| "to_u128"
|
||||
| "to_i128"
|
||||
| "to_u64"
|
||||
| "to_i64"
|
||||
| "to_u32"
|
||||
| "to_i32"
|
||||
| "to_u16"
|
||||
| "to_i16"
|
||||
| "to_u8"
|
||||
| "to_i8"
|
||||
| "replace_each"
|
||||
| "replace_first"
|
||||
| "replace_last"
|
||||
| "split_first"
|
||||
| "split_last"
|
||||
| "walk_utf8"
|
||||
| "walk_utf8_with_index"
|
||||
| "reserve"
|
||||
| "release_excess_capacity"
|
||||
| "with_prefix"
|
||||
| "contains"
|
||||
| "drop_prefix"
|
||||
| "drop_suffix"
|
||||
| "with_ascii_lowercased"
|
||||
| "with_ascii_uppercased"
|
||||
| "caseless_ascii_equals"
|
||||
),
|
||||
|
||||
// TODO: other modules
|
||||
"List" => matches!(
|
||||
ident,
|
||||
"is_empty"
|
||||
| "get"
|
||||
| "set"
|
||||
| "replace"
|
||||
| "update"
|
||||
| "append"
|
||||
| "append_if_ok"
|
||||
| "prepend"
|
||||
| "prepend_if_ok"
|
||||
| "map"
|
||||
| "len"
|
||||
| "walk_backwards"
|
||||
| "concat"
|
||||
| "first"
|
||||
| "single"
|
||||
| "repeat"
|
||||
| "reverse"
|
||||
| "join"
|
||||
| "keep_if"
|
||||
| "contains"
|
||||
| "sum"
|
||||
| "walk"
|
||||
| "last"
|
||||
| "keep_oks"
|
||||
| "keep_errs"
|
||||
| "map_with_index"
|
||||
| "map2"
|
||||
| "map3"
|
||||
| "product"
|
||||
| "walk_with_index"
|
||||
| "walk_until"
|
||||
| "walk_with_index_until"
|
||||
| "walk_from"
|
||||
| "walk_from_until"
|
||||
| "range"
|
||||
| "sort_with"
|
||||
| "swap"
|
||||
| "drop_at"
|
||||
| "min"
|
||||
| "max"
|
||||
| "map4"
|
||||
| "map_try"
|
||||
| "walk_try"
|
||||
| "join_map"
|
||||
| "any"
|
||||
| "take_first"
|
||||
| "take_last"
|
||||
| "drop_first"
|
||||
| "drop_last"
|
||||
| "find_first"
|
||||
| "find_last"
|
||||
| "find_first_index"
|
||||
| "find_last_index"
|
||||
| "sublist"
|
||||
| "intersperse"
|
||||
| "split_at"
|
||||
| "split_on"
|
||||
| "split_on_list"
|
||||
| "split_first"
|
||||
| "split_last"
|
||||
| "starts_with"
|
||||
| "ends_with"
|
||||
| "all"
|
||||
| "drop_if"
|
||||
| "sort_asc"
|
||||
| "sort_desc"
|
||||
| "reserve"
|
||||
| "release_excess_capacity"
|
||||
| "walk_backwards_until"
|
||||
| "count_if"
|
||||
| "chunks_of"
|
||||
| "concat_utf8"
|
||||
| "for_each!"
|
||||
| "for_each_try!"
|
||||
| "walk!"
|
||||
| "walk_try!"
|
||||
),
|
||||
"Dict" => {
|
||||
matches!(
|
||||
ident,
|
||||
"clear"
|
||||
| "capacity"
|
||||
| "reserve"
|
||||
| "release_excess_capacity"
|
||||
| "len"
|
||||
| "is_empty"
|
||||
| "get"
|
||||
| "contains"
|
||||
| "insert"
|
||||
| "remove"
|
||||
| "update"
|
||||
| "walk"
|
||||
| "walk_until"
|
||||
| "keep_if"
|
||||
| "drop_if"
|
||||
| "to_list"
|
||||
| "keys"
|
||||
| "values"
|
||||
| "insert_all"
|
||||
| "keep_shared"
|
||||
| "remove_all"
|
||||
| "map"
|
||||
| "join_map"
|
||||
)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn migrate_pizza<'a>(
|
||||
buf: &Buf<'a>,
|
||||
arena: &'a Bump,
|
||||
expr_op_pairs: &[(Loc<Expr<'a>>, Loc<BinOp>)],
|
||||
last_expr: Loc<Expr<'a>>,
|
||||
) -> Result<MigratedBinOp<'a>, MigrateError> {
|
||||
println!(
|
||||
"Starting migrate_pizza with {} expr_op_pairs",
|
||||
expr_op_pairs.len()
|
||||
);
|
||||
|
||||
let mut stack: Vec<MigratedBinOp<'a>> = Vec::new();
|
||||
let mut ops: Vec<BinOp> = Vec::new();
|
||||
|
||||
for (expr, op) in expr_op_pairs {
|
||||
println!("Processing expression: {:?}", expr.value);
|
||||
stack.push(MigratedBinOp::Expr(expr.value));
|
||||
apply_ops(buf, arena, &mut stack, &mut ops, op.value.precedence())?;
|
||||
|
||||
println!("Pushing operator onto stack: {:?}", op.value);
|
||||
ops.push(op.value);
|
||||
}
|
||||
|
||||
// Push the last expression onto the stack
|
||||
println!("Pushing last expression onto stack: {:?}", last_expr.value);
|
||||
stack.push(MigratedBinOp::Expr(last_expr.value));
|
||||
|
||||
// Apply all remaining operators
|
||||
println!("Applying all remaining operators (min_precedence: 0)");
|
||||
apply_ops(buf, arena, &mut stack, &mut ops, 0)?;
|
||||
println!("Final stack size: {}", stack.len());
|
||||
|
||||
// The final result should be at the top of the stack
|
||||
let result = stack.pop().unwrap();
|
||||
println!("Returning final result: {:?}", result);
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn fmt_converted_ops(
|
||||
buf: &mut Buf,
|
||||
indent: u16,
|
||||
converted: &MigratedBinOp,
|
||||
suffix: Suffix,
|
||||
) -> Result<(), MigrateError> {
|
||||
match converted {
|
||||
MigratedBinOp::BinOp { lhs, op, rhs } => {
|
||||
// Format left-hand side
|
||||
fmt_converted_ops(buf, indent, lhs, Suffix::None)?;
|
||||
|
||||
// Format operator
|
||||
buf.indent(indent);
|
||||
buf.spaces(1);
|
||||
push_op(buf, *op);
|
||||
buf.spaces(1);
|
||||
|
||||
// Format right-hand side
|
||||
fmt_converted_ops(buf, indent, rhs, suffix)?;
|
||||
}
|
||||
MigratedBinOp::Expr(expr) => {
|
||||
fmt_expr(buf, indent, expr, suffix)?;
|
||||
}
|
||||
MigratedBinOp::Parens(inner) => {
|
||||
buf.push('(');
|
||||
fmt_converted_ops(buf, indent, inner, Suffix::None)?;
|
||||
buf.indent(indent);
|
||||
buf.push(')');
|
||||
fmt_suffix(buf, indent, suffix);
|
||||
}
|
||||
MigratedBinOp::StaticDispatch {
|
||||
lhs,
|
||||
before,
|
||||
func,
|
||||
args,
|
||||
after,
|
||||
} => {
|
||||
// lhs.func(args)
|
||||
fmt_converted_ops(buf, indent, lhs, Suffix::None)?;
|
||||
if !before.is_empty() {
|
||||
fmt_spaces(buf, before.iter(), indent);
|
||||
}
|
||||
buf.indent(indent);
|
||||
buf.push('.');
|
||||
buf.push_str(func);
|
||||
buf.push('(');
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
fmt_expr(buf, indent, arg, Suffix::None)?;
|
||||
if i != args.len() - 1 {
|
||||
buf.indent(indent);
|
||||
buf.push(',');
|
||||
buf.spaces(1);
|
||||
}
|
||||
}
|
||||
buf.indent(indent);
|
||||
buf.push(')');
|
||||
fmt_suffix(buf, indent, suffix);
|
||||
if !after.is_empty() {
|
||||
fmt_spaces(buf, after.iter(), indent);
|
||||
}
|
||||
}
|
||||
MigratedBinOp::FuncStaticDispatch {
|
||||
lhs,
|
||||
before,
|
||||
func,
|
||||
args,
|
||||
after,
|
||||
} => {
|
||||
// lhs.(func)(args)
|
||||
fmt_converted_ops(buf, indent, lhs, Suffix::None)?;
|
||||
if !before.is_empty() {
|
||||
fmt_spaces(buf, before.iter(), indent);
|
||||
}
|
||||
buf.indent(indent);
|
||||
buf.push('.');
|
||||
buf.push('(');
|
||||
fmt_expr(buf, indent, func, Suffix::None)?;
|
||||
buf.push(')');
|
||||
buf.push('(');
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
fmt_expr(buf, indent, arg, Suffix::None)?;
|
||||
if i != args.len() - 1 {
|
||||
buf.indent(indent);
|
||||
buf.push(',');
|
||||
buf.spaces(1);
|
||||
}
|
||||
}
|
||||
buf.indent(indent);
|
||||
buf.push(')');
|
||||
fmt_suffix(buf, indent, suffix);
|
||||
if !after.is_empty() {
|
||||
fmt_spaces(buf, after.iter(), indent);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn fmt_expr_top_level(
|
||||
buf: &mut Buf<'_>,
|
||||
indent: u16,
|
||||
|
@ -691,8 +1157,16 @@ fn fmt_collection<F: Fmt>(
|
|||
}
|
||||
}
|
||||
|
||||
for item in collection.iter() {
|
||||
item.fmt(buf, indent + 4, Suffix::Comma)?;
|
||||
for (i, item) in collection.iter().enumerate() {
|
||||
let is_last = i == collection.len() - 1 && tail.is_none();
|
||||
item.fmt(
|
||||
buf,
|
||||
indent + 4,
|
||||
if is_last { Suffix::None } else { Suffix::Comma },
|
||||
)?;
|
||||
if !is_last {
|
||||
buf.spaces(1);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(tail) = tail {
|
||||
|
@ -743,12 +1217,22 @@ impl Fmt for TypeHeader<'_> {
|
|||
fn fmt(&self, buf: &mut Buf, indent: u16, suffix: Suffix) -> Result<(), MigrateError> {
|
||||
buf.indent(indent);
|
||||
buf.push_str(self.name.value);
|
||||
if !self.vars.is_empty() {
|
||||
buf.push('(');
|
||||
for arg in self.vars {
|
||||
arg.fmt(buf, indent, Suffix::Comma)?;
|
||||
for (i, arg) in self.vars.iter().enumerate() {
|
||||
let is_last = i == self.vars.len() - 1;
|
||||
arg.fmt(
|
||||
buf,
|
||||
indent,
|
||||
if is_last { Suffix::None } else { Suffix::Comma },
|
||||
)?;
|
||||
if !is_last {
|
||||
buf.spaces(1);
|
||||
}
|
||||
}
|
||||
buf.indent(indent);
|
||||
buf.push(')');
|
||||
}
|
||||
fmt_suffix(buf, indent, suffix);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -762,8 +1246,16 @@ impl Fmt for Tag<'_> {
|
|||
buf.push_str(name.value);
|
||||
if !args.is_empty() {
|
||||
buf.push('(');
|
||||
for arg in args.iter() {
|
||||
arg.fmt(buf, indent, Suffix::Comma)?;
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
let is_last = i == args.len() - 1;
|
||||
arg.fmt(
|
||||
buf,
|
||||
indent,
|
||||
if is_last { Suffix::None } else { Suffix::Comma },
|
||||
)?;
|
||||
if !is_last {
|
||||
buf.spaces(1);
|
||||
}
|
||||
}
|
||||
buf.indent(indent);
|
||||
buf.push(')');
|
||||
|
@ -788,8 +1280,16 @@ impl Fmt for TypeAnnotation<'_> {
|
|||
fn fmt(&self, buf: &mut Buf, indent: u16, suffix: Suffix) -> Result<(), MigrateError> {
|
||||
match self {
|
||||
TypeAnnotation::Function(args, function_arrow, res) => {
|
||||
for arg in args.iter() {
|
||||
arg.fmt(buf, indent, Suffix::Comma)?;
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
let is_last = i == args.len() - 1;
|
||||
arg.fmt(
|
||||
buf,
|
||||
indent,
|
||||
if is_last { Suffix::None } else { Suffix::Comma },
|
||||
)?;
|
||||
if !is_last {
|
||||
buf.spaces(1);
|
||||
}
|
||||
}
|
||||
match function_arrow {
|
||||
FunctionArrow::Pure => {
|
||||
|
@ -811,8 +1311,16 @@ impl Fmt for TypeAnnotation<'_> {
|
|||
buf.push_str(func);
|
||||
if !locs.is_empty() {
|
||||
buf.push('(');
|
||||
for loc in locs.iter() {
|
||||
loc.fmt(buf, indent, Suffix::Comma)?;
|
||||
for (i, loc) in locs.iter().enumerate() {
|
||||
let is_last = i == locs.len() - 1;
|
||||
loc.fmt(
|
||||
buf,
|
||||
indent,
|
||||
if is_last { Suffix::None } else { Suffix::Comma },
|
||||
)?;
|
||||
if !is_last {
|
||||
buf.spaces(1);
|
||||
}
|
||||
}
|
||||
buf.indent(indent);
|
||||
buf.push(')');
|
||||
|
@ -865,8 +1373,7 @@ impl Fmt for TypeAnnotation<'_> {
|
|||
buf.push_str("_");
|
||||
}
|
||||
TypeAnnotation::Wildcard => {
|
||||
buf.indent(indent);
|
||||
buf.push_str("*");
|
||||
return Err(MigrateError::WildcardTypeNotSupported);
|
||||
}
|
||||
TypeAnnotation::Where(left, clauses) => {
|
||||
left.fmt(buf, indent, Suffix::None)?;
|
||||
|
@ -1022,6 +1529,11 @@ impl Fmt for TypeDef<'_> {
|
|||
typ,
|
||||
derived,
|
||||
} => {
|
||||
if true {
|
||||
// current new compiler doesn't support opaque types
|
||||
// TODO: fix this!
|
||||
return Err(MigrateError::OpaqueNotSupported);
|
||||
}
|
||||
header.fmt(buf, indent, Suffix::None)?;
|
||||
buf.push_str(" :=");
|
||||
buf.spaces(1);
|
||||
|
@ -1046,11 +1558,14 @@ impl Fmt for TypeDef<'_> {
|
|||
#[derive(Debug)]
|
||||
pub enum MigrateError {
|
||||
AbilitiesNotSupported,
|
||||
WildcardTypeNotSupported,
|
||||
MalformedIdentNotSupported,
|
||||
MalformedPatternNotSupported,
|
||||
MalformedPatternIdentNotSupported,
|
||||
MalformedPatternAsExprNotSupported,
|
||||
PrecedenceConflictNotSupported,
|
||||
OpaqueNotSupported,
|
||||
PizzaOpRhsNotSupported,
|
||||
}
|
||||
|
||||
impl Fmt for ValueDef<'_> {
|
||||
|
@ -1133,6 +1648,7 @@ impl Fmt for IngestedFileImport<'_> {
|
|||
|
||||
buf.indent(indent);
|
||||
buf.push_str("import");
|
||||
buf.spaces(1);
|
||||
|
||||
let indent = indent + 4;
|
||||
|
||||
|
@ -1236,6 +1752,7 @@ impl Fmt for ModuleImport<'_> {
|
|||
|
||||
buf.indent(indent);
|
||||
buf.push_str("import");
|
||||
buf.spaces(1);
|
||||
|
||||
if !before_name.is_empty() {
|
||||
fmt_spaces(buf, before_name.iter(), indent);
|
||||
|
@ -1250,10 +1767,13 @@ impl Fmt for ModuleImport<'_> {
|
|||
}
|
||||
|
||||
if let Some(exposed) = exposed {
|
||||
buf.spaces(1);
|
||||
exposed.keyword.fmt(buf, indent, Suffix::None)?;
|
||||
buf.spaces(1);
|
||||
fmt_collection(buf, indent, Braces::Square, None, exposed.item, None)?;
|
||||
}
|
||||
fmt_suffix(buf, indent, suffix);
|
||||
buf.ensure_ends_with_newline();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1399,3 +1919,9 @@ pub fn fmt_defs(buf: &mut Buf<'_>, defs: &Defs<'_>) -> Result<(), MigrateError>
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn snakify_camel_ident_in_bump<'a>(arena: &'a Bump, string: &str) -> String<'a> {
|
||||
let mut buf = Buf::new_in(arena, MigrationFlags::default());
|
||||
snakify_camel_ident(&mut buf, string);
|
||||
buf.text
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ impl BinOp {
|
|||
ASSOCIATIVITY_TABLE[self as usize]
|
||||
}
|
||||
|
||||
fn precedence(self) -> u8 {
|
||||
pub fn precedence(self) -> u8 {
|
||||
const PRECEDENCE_TABLE: [u8; 18] = generate_precedence_table();
|
||||
|
||||
PRECEDENCE_TABLE[self as usize]
|
||||
|
|
|
@ -5,6 +5,6 @@ O({p: if
|
|||
A
|
||||
} else {
|
||||
&m
|
||||
}}, #
|
||||
}} #
|
||||
) : e
|
||||
i
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
N((implements),h,(0),) : B
|
||||
N((implements), h, (0)) : B
|
||||
T
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
N(-0,T,) : A
|
||||
N(-0, T) : A
|
||||
zT
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
B(@A,) : w
|
||||
B(@A) : w
|
||||
#
|
||||
@A = e
|
||||
i
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
Zx((e #
|
||||
),f,) : i
|
||||
), f) : i
|
||||
s
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
U((b(a,)),) : b
|
||||
U((b(a))) : b
|
||||
a
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
M({s: s({J&
|
||||
},)},{s: s({J&
|
||||
},)},) : p
|
||||
})}, {s: s({J&
|
||||
})}) : p
|
||||
y
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Q((
|
||||
"""
|
||||
"""("",)),) : a
|
||||
"""(""))) : a
|
||||
q
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
il3(|k| # w#z
|
||||
{
|
||||
CCC(@C, ( # i
|
||||
t!(K,)),) : i
|
||||
t!(K))) : i
|
||||
C
|
||||
},)
|
||||
})
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
M() :
|
||||
M :
|
||||
r
|
||||
h
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
A( #
|
||||
p,) : e
|
||||
p) : e
|
||||
A
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
K() : #
|
||||
K : #
|
||||
s
|
||||
K
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
O() : O(z,
|
||||
O : O(z
|
||||
#
|
||||
)
|
||||
b #
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
8: O(
|
||||
{
|
||||
},)
|
||||
})
|
||||
Q
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
foo: [True,Perhaps(Thing,),]
|
||||
foo: [True, Perhaps(Thing)]
|
||||
foo = True
|
||||
|
||||
42
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
launchTheNukes: {}, => Result(Bool,LaunchNukeErr,)
|
||||
launchTheNukes: {} => Result(Bool, LaunchNukeErr)
|
||||
launchTheNukes = |{}|
|
||||
crash("todo",)
|
||||
crash("todo")
|
||||
|
||||
launchTheNukes
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
x: a
|
||||
where
|
||||
e
|
||||
implements K, -> Z
|
||||
implements K -> Z
|
||||
s
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
H() : p
|
||||
H : p
|
||||
#
|
||||
s = p
|
||||
d #
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{l: s, #
|
||||
{l: s #
|
||||
}: s
|
||||
o
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
J() : [
|
||||
J : [
|
||||
] where e
|
||||
implements T
|
||||
i
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
1: (f,
|
||||
ww, -> p,..e)
|
||||
ww -> p, ..e)
|
||||
Mh
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{x,y,}: Foo
|
||||
{x,y,} = {x: "foo"y: 3.14}
|
||||
{x, y}: Foo
|
||||
{x, y} = {x: "foo", y: 3.14}
|
||||
|
||||
x
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
UserId(x,): [UserId(I64,),]
|
||||
UserId(x,) = UserId(42,)
|
||||
UserId(x): [UserId(I64)]
|
||||
UserId(x) = UserId(42)
|
||||
|
||||
x
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
(x,y,): Foo
|
||||
(x,y,) = ("foo",3.14,)
|
||||
(x, y): Foo
|
||||
(x, y) = ("foo", 3.14)
|
||||
|
||||
x
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
A(
|
||||
p,) :
|
||||
p) :
|
||||
e
|
||||
A
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
e: A #
|
||||
as H()
|
||||
as H
|
||||
n
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
A(
|
||||
e, # g
|
||||
e # g
|
||||
) : A
|
||||
AA
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
s: eas A()as A()
|
||||
s: eas Aas A
|
||||
s
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
g: [T(T, #
|
||||
),]
|
||||
g: [T(T #
|
||||
)]
|
||||
D
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
3: (..n #
|
||||
), -> n
|
||||
) -> n
|
||||
0
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
Str.getUnsafe(haystack,haystackIndex,)
|
||||
Str.getUnsafe(haystack, haystackIndex)
|
||||
==
|
||||
Str.getUnsafe(needle,needleIndex,)
|
||||
Str.getUnsafe(needle, needleIndex)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
!!
|
||||
|w| 2(
|
||||
n,)
|
||||
n)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
foo
|
||||
|> Dict.keepIf(|(k,_v,)| List.contains(keysToDelete,k,) |> Bool.not,)
|
||||
.(Dict.keepIf)(|(k, _v)| List.contains(keysToDelete, k).(Bool.not)())
|
||||
|
|
|
@ -1 +1 @@
|
|||
Whee((12),(34),)
|
||||
Whee((12), (34))
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
a: N({h
|
||||
},)
|
||||
})
|
||||
g
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
0({l xt l: (se #
|
||||
)},)
|
||||
)})
|
||||
|
|
|
@ -1 +1 @@
|
|||
Whee(12,34,)
|
||||
Whee(12, 34)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Whee(12,34,)
|
||||
Whee(12, 34)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Ok(a,)
|
||||
Ok(a)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Ok(a,)
|
||||
Ok(a)
|
||||
|
|
|
@ -1 +1 @@
|
|||
a(b,c,d,)
|
||||
a(b, c, d)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
i: M((),c,)
|
||||
i: M((), c)
|
||||
t
|
||||
|
|
|
@ -1 +1 @@
|
|||
whee(12,34,)
|
||||
whee(12, 34)
|
||||
|
|
|
@ -1 +1 @@
|
|||
whee(12,34,)
|
||||
whee(12, 34)
|
||||
|
|
|
@ -1 +1 @@
|
|||
-whee(12,foo,)
|
||||
-whee(12, foo)
|
||||
|
|
|
@ -1 +1 @@
|
|||
!whee(12,foo,)
|
||||
!whee(12, foo)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
|{x,y,} as point@Location(inner,) as outer|
|
||||
crash("",)
|
||||
|{x, y} as point@Location(inner) as outer|
|
||||
crash("")
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
e: J
|
||||
as H(), -> A
|
||||
as H -> A
|
||||
r
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
J
|
||||
!
|
||||
.1(!.0,)
|
||||
.1(!.0)
|
||||
|
|
|
@ -1 +1 @@
|
|||
whee(1,)
|
||||
whee(1)
|
||||
|
|
|
@ -1 +1 @@
|
|||
(1,2,3,)
|
||||
(1, 2, 3)
|
||||
|
|
|
@ -1 +1 @@
|
|||
N < l((r * N),)
|
||||
N < l((r * N))
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
d +
|
||||
(|w| x)(
|
||||
x,)
|
||||
x)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
r ^
|
||||
-f(
|
||||
#
|
||||
-P,)
|
||||
-P)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
t =
|
||||
"""
|
||||
"
|
||||
"""("",)
|
||||
"""("")
|
||||
S
|
||||
|
|
|
@ -1 +1 @@
|
|||
launchTheNukes!(123,)
|
||||
launchTheNukes!(123)
|
||||
|
|
|
@ -1 +1 @@
|
|||
fxFn!(arg,)
|
||||
fxFn!(arg)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import P{_: h
|
||||
}
|
||||
|
||||
t!
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|I({p? Y(
|
||||
Y,)?,},[
|
||||
],)|
|
||||
Y)?},[
|
||||
])|
|
||||
K # (
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
m0(|w| w?(e,),)
|
||||
m0(|w| w?(e))
|
||||
/ s
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
|L(z,
|
||||
|L(z
|
||||
|
||||
)| 42
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
|{i, #
|
||||
e,}| a
|
||||
e}| a
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
m
|
||||
^ (-|w| m)(
|
||||
w,)
|
||||
w)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
Model(position,) :
|
||||
{evaluated: Set(position,)
|
||||
openSet: Set(position,)
|
||||
costs: Dict.Dict(position,F64,)
|
||||
cameFrom: Dict.Dict(position,position,)
|
||||
Model(position) :
|
||||
{evaluated: Set(position),
|
||||
openSet: Set(position),
|
||||
costs: Dict.Dict(position, F64),
|
||||
cameFrom: Dict.Dict(position, position)
|
||||
}
|
||||
|
||||
a
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
F() : e #
|
||||
F : e #
|
||||
|
||||
q
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
dbg(l,) #
|
||||
dbg(l) #
|
||||
n
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
PP(P(@P(P(
|
||||
P(PPP(P(
|
||||
PPP,),
|
||||
),
|
||||
),
|
||||
PP(mport, # <|"P
|
||||
),),
|
||||
),),
|
||||
PPP)
|
||||
)
|
||||
),
|
||||
PP(mport # <|"P
|
||||
))
|
||||
))
|
||||
)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
1: (M, b, # ,
|
||||
h, -> g,..e)
|
||||
h -> g, ..e)
|
||||
h
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
|L( #
|
||||
i,)| -e
|
||||
i)| -e
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
|LM( #
|
||||
Q,)| f8
|
||||
Q)| f8
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
1(0, #
|
||||
1(0 #
|
||||
#
|
||||
): gi
|
||||
M
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
x >
|
||||
x({
|
||||
|
||||
},) < r
|
||||
}) < r
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
_ = crash("",)
|
||||
_ = crash("","",)
|
||||
_ = crash(15,123,)
|
||||
_ = try(foo,(|_| crash("",)),)
|
||||
_ = crash("")
|
||||
_ = crash("", "")
|
||||
_ = crash(15, 123)
|
||||
_ = try(foo, (|_| crash("")))
|
||||
_ =
|
||||
{
|
||||
_ = crash("",)
|
||||
_ = crash("")
|
||||
crash
|
||||
}
|
||||
|
||||
{f: crash("",)}
|
||||
{f: crash("")}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
1(0( #
|
||||
0,),
|
||||
)(f,): f
|
||||
0)
|
||||
)(f): f
|
||||
t
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
1(ts(0,
|
||||
1(ts(0
|
||||
|
||||
#
|
||||
),
|
||||
)(f,): i7f
|
||||
)
|
||||
)(f): i7f
|
||||
e
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
-
|
||||
"""
|
||||
"""()?
|
||||
}))(Y,)
|
||||
}))(Y)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
0(
|
||||
#
|
||||
f,): f
|
||||
f): f
|
||||
t
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
1: w, -> w, -> p
|
||||
1: w -> w -> p
|
||||
h
|
||||
|
|
|
@ -1 +1 @@
|
|||
dbg(1,)
|
||||
dbg(1)
|
||||
|
|
|
@ -1 +1 @@
|
|||
dbg(dbg,g,g,)
|
||||
dbg(dbg, g, g)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
dbg(dbg,
|
||||
a,g,)
|
||||
a, g)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
dbg(d,z,)
|
||||
dbg(d, z)
|
||||
dd
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
dbg(
|
||||
|
||||
izzb,
|
||||
interfacesb,)
|
||||
interfacesb)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
dbg(a / a,)
|
||||
dbg(a / a)
|
||||
d
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
({
|
||||
(dbg(r,))
|
||||
(dbg(r))
|
||||
r
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
dbg (5,
|
||||
666,)
|
||||
666)
|
||||
|
||||
4
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
dbg
|
||||
(q(
|
||||
qt,))
|
||||
qt))
|
||||
|
||||
g(
|
||||
qt,)
|
||||
qt)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
launchTheNukes! = |{}|
|
||||
boom
|
||||
|
||||
launchTheNukes!({},)
|
||||
launchTheNukes!({})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
e =
|
||||
"""
|
||||
"""(a,)
|
||||
"""(a)
|
||||
p
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
main =
|
||||
{
|
||||
a = "Foo"
|
||||
Stdout.line?(a,)
|
||||
Stdout.line?(a)
|
||||
|
||||
printBar?
|
||||
}
|
||||
|
@ -9,5 +9,5 @@ main =
|
|||
printBar =
|
||||
{
|
||||
b = "Bar"
|
||||
Stdout.line(b,)
|
||||
Stdout.line(b)
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Email(str,) = Email("blah@example.com",)
|
||||
Email(str) = Email("blah@example.com")
|
||||
str
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
|j| e(|B
|
||||
| B,)
|
||||
| B)
|
||||
> s
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
1: (w, -> p,
|
||||
w, -> p,)
|
||||
1: (w -> p,
|
||||
w -> p)
|
||||
h
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
(0( #
|
||||
e,),0( #
|
||||
p,),): f
|
||||
e), 0( #
|
||||
p)): f
|
||||
t #
|
||||
|
|
|
@ -1 +1 @@
|
|||
get_name!({},) ?? "Bob"
|
||||
get_name!({}) ?? "Bob"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue