Skip to content

Commit

Permalink
Fix this params
Browse files Browse the repository at this point in the history
  • Loading branch information
voltrevo committed Jul 6, 2023
1 parent a3ae60e commit 2952d69
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 67 deletions.
21 changes: 3 additions & 18 deletions inputs/passing/helpers/Range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,7 @@ export default class Range<T = never> implements Iterable<T> {
return res;
}

sum(
// Warning: ValueScript has a bug where typing the `this` parameter causes it to create a
// phantom regular parameter. This only works because there aren't any other parameters.
// TODO: Fix this.
this: Range<number>,
) {
sum(this: Range<number>) {
let res = 0;

for (const x of this.iterable) {
Expand All @@ -82,12 +77,7 @@ export default class Range<T = never> implements Iterable<T> {
return res;
}

bigSum(
// Warning: ValueScript has a bug where typing the `this` parameter causes it to create a
// phantom regular parameter. This only works because there aren't any other parameters.
// TODO: Fix this.
this: Range<bigint>,
) {
bigSum(this: Range<bigint>) {
let res = 0n;

for (const x of this.iterable) {
Expand All @@ -107,12 +97,7 @@ export default class Range<T = never> implements Iterable<T> {
return res;
}

bigProduct(
// Warning: ValueScript has a bug where typing the `this` parameter causes it to create a
// phantom regular parameter. This only works because there aren't any other parameters.
// TODO: Fix this.
this: Range<bigint>,
) {
bigProduct(this: Range<bigint>) {
let res = 1n;

for (const x of this.iterable) {
Expand Down
3 changes: 1 addition & 2 deletions inputs/failing/thisParam.ts → inputs/passing/thisParam.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//! test_output(NaN)
// Should be: 10
//! test_output(10)

export default function () {
return foo(5);
Expand Down
25 changes: 22 additions & 3 deletions valuescript_compiler/src/expression_compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,13 @@ impl<'a> ExpressionCompiler<'a> {

match pat {
Pat::Ident(ident) => {
let ident_reg = self.fnc.get_pattern_register(pat);
let ident_reg = match self.fnc.get_pattern_register(pat) {
Some(r) => r,
None => {
self.fnc.error(pat.span(), &"Invalid pattern".to_string());
self.fnc.allocate_reg(&"_invalid_pattern".to_string())
}
};

if register != &ident_reg {
self.fnc.diagnostics.push(Diagnostic {
Expand Down Expand Up @@ -1425,7 +1431,13 @@ impl<'a> ExpressionCompiler<'a> {
None => continue,
};

let elem_reg = self.fnc.get_pattern_register(elem);
let elem_reg = match self.fnc.get_pattern_register(elem) {
Some(r) => r,
None => {
self.fnc.error(elem.span(), "Invalid pattern");
self.fnc.allocate_reg(&"_invalid_pattern".to_string())
}
};

self.fnc.push(Instruction::Sub(
Value::Register(register.clone()),
Expand All @@ -1446,7 +1458,14 @@ impl<'a> ExpressionCompiler<'a> {

match prop {
ObjectPatProp::KeyValue(kv) => {
let param_reg = self.fnc.get_pattern_register(&kv.value);
let param_reg = match self.fnc.get_pattern_register(&kv.value) {
Some(r) => r,
None => {
self.fnc.error(kv.value.span(), "Invalid pattern");
self.fnc.allocate_reg(&"_invalid_pattern".to_string())
}
};

let compiled_key = self.prop_name(&kv.key);

self.fnc.push(Instruction::Sub(
Expand Down
88 changes: 62 additions & 26 deletions valuescript_compiler/src/function_compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ impl FunctionCompiler {
});
}

pub fn error(&mut self, span: swc_common::Span, message: &str) {
self.diagnostics.push(Diagnostic {
level: DiagnosticLevel::Error,
message: format!("{}", message),
span,
});
}

pub fn internal_error(&mut self, span: swc_common::Span, message: &str) {
self.diagnostics.push(Diagnostic {
level: DiagnosticLevel::InternalError,
Expand Down Expand Up @@ -311,7 +319,9 @@ impl FunctionCompiler {
let param_registers = self.get_param_registers(functionish);

for reg in &param_registers {
self.current.parameters.push(reg.clone());
if let Some(reg) = reg {
self.current.parameters.push(reg.clone());
}
}

self.add_param_code(functionish, &param_registers);
Expand Down Expand Up @@ -372,8 +382,8 @@ impl FunctionCompiler {
}
}

fn get_param_registers(&mut self, functionish: &Functionish) -> Vec<Register> {
let mut param_registers = Vec::<Register>::new();
fn get_param_registers(&mut self, functionish: &Functionish) -> Vec<Option<Register>> {
let mut param_registers = Vec::<Option<Register>>::new();

match functionish {
Functionish::Fn(_, fn_) => {
Expand All @@ -391,7 +401,9 @@ impl FunctionCompiler {
match potspp {
swc_ecma_ast::ParamOrTsParamProp::TsParamProp(ts_param_prop) => {
self.todo(ts_param_prop.span(), "TypeScript parameter properties");
param_registers.push(self.allocate_numbered_reg(&"_todo_ts_param_prop".to_string()));
param_registers.push(Some(
self.allocate_numbered_reg(&"_todo_ts_param_prop".to_string()),
));
}
swc_ecma_ast::ParamOrTsParamProp::Param(p) => {
param_registers.push(self.get_pattern_register(&p.pat))
Expand All @@ -404,18 +416,21 @@ impl FunctionCompiler {
return param_registers;
}

pub fn get_pattern_register(&mut self, param_pat: &swc_ecma_ast::Pat) -> Register {
pub fn get_pattern_register(&mut self, param_pat: &swc_ecma_ast::Pat) -> Option<Register> {
use swc_ecma_ast::Pat;

match param_pat {
Pat::Ident(ident) => self.get_variable_register(&ident.id),
Pat::Assign(assign) => self.get_pattern_register(&assign.left),
Some(match param_pat {
Pat::Ident(ident) => match ident.id.sym.to_string().as_str() {
"this" => return None,
_ => self.get_variable_register(&ident.id),
},
Pat::Assign(assign) => return self.get_pattern_register(&assign.left),
Pat::Array(_) => self.allocate_numbered_reg(&"_array_pat".to_string()),
Pat::Object(_) => self.allocate_numbered_reg(&"_object_pat".to_string()),
Pat::Invalid(_) => self.allocate_numbered_reg(&"_invalid_pat".to_string()),
Pat::Rest(_) => self.allocate_numbered_reg(&"_rest_pat".to_string()),
Pat::Expr(_) => self.allocate_numbered_reg(&"_expr_pat".to_string()),
}
})
}

pub fn get_variable_register(&mut self, ident: &swc_ecma_ast::Ident) -> Register {
Expand All @@ -437,18 +452,22 @@ impl FunctionCompiler {
}
}

fn add_param_code(&mut self, functionish: &Functionish, param_registers: &Vec<Register>) {
fn add_param_code(&mut self, functionish: &Functionish, param_registers: &Vec<Option<Register>>) {
match functionish {
Functionish::Fn(_, fn_) => {
for (i, p) in fn_.params.iter().enumerate() {
let mut ec = ExpressionCompiler { fnc: self };
ec.pat(&p.pat, &param_registers[i], false);
if let Some(reg) = &param_registers[i] {
let mut ec = ExpressionCompiler { fnc: self };
ec.pat(&p.pat, reg, false);
}
}
}
Functionish::Arrow(arrow) => {
for (i, p) in arrow.params.iter().enumerate() {
let mut ec = ExpressionCompiler { fnc: self };
ec.pat(p, &param_registers[i], false);
if let Some(reg) = &param_registers[i] {
let mut ec = ExpressionCompiler { fnc: self };
ec.pat(p, reg, false);
}
}
}
Functionish::Constructor(_, _class_span, constructor) => {
Expand All @@ -458,8 +477,10 @@ impl FunctionCompiler {
// TODO (Diagnostic emitted elsewhere)
}
swc_ecma_ast::ParamOrTsParamProp::Param(p) => {
let mut ec = ExpressionCompiler { fnc: self };
ec.pat(&p.pat, &param_registers[i], false);
if let Some(reg) = &param_registers[i] {
let mut ec = ExpressionCompiler { fnc: self };
ec.pat(&p.pat, reg, false);
}
}
}
}
Expand Down Expand Up @@ -828,15 +849,17 @@ impl FunctionCompiler {
if let Some(param) = &catch_clause.param {
let mut ec = ExpressionCompiler { fnc: self };

let pattern_reg = ec.fnc.get_pattern_register(&param);

// TODO: Set up this register through set_catch instead of copying into it
ec.fnc.push(Instruction::Mov(
Value::Register(catch_error_reg.unwrap()),
pattern_reg.clone(),
));
if let Some(pattern_reg) = ec.fnc.get_pattern_register(&param) {
// TODO: Set up this register through set_catch instead of copying into it
ec.fnc.push(Instruction::Mov(
Value::Register(catch_error_reg.unwrap()),
pattern_reg.clone(),
));

ec.pat(&param, &pattern_reg, false);
ec.pat(&param, &pattern_reg, false);
} else {
ec.fnc.error(param.span(), "Invalid catch pattern");
}
}

self.block_statement(&catch_clause.body);
Expand Down Expand Up @@ -1109,7 +1132,14 @@ impl FunctionCompiler {
swc_ecma_ast::VarDeclOrPat::Pat(pat) => pat,
};

let value_reg = ec.fnc.get_pattern_register(pat);
let value_reg = match ec.fnc.get_pattern_register(pat) {
Some(value_reg) => value_reg,
None => {
ec.fnc
.error(pat.span(), "Loop variable has invalid pattern");
ec.fnc.allocate_reg(&"_invalid_pattern".to_string())
}
};

let iter_reg = ec.fnc.allocate_numbered_reg(&"_iter".to_string());
let iter_res_reg = ec.fnc.allocate_numbered_reg(&"_iter_res".to_string());
Expand Down Expand Up @@ -1225,7 +1255,13 @@ impl FunctionCompiler {
for decl in &var_decl.decls {
match &decl.init {
Some(expr) => {
let target_register = self.get_pattern_register(&decl.name);
let target_register = match self.get_pattern_register(&decl.name) {
Some(tr) => tr,
None => {
self.error(decl.name.span(), "Invalid pattern");
self.allocate_reg(&"_invalid_pattern".to_string())
}
};

let mut ec = ExpressionCompiler { fnc: self };
ec.compile_into(expr, target_register.clone());
Expand Down
21 changes: 3 additions & 18 deletions website/src/playground/files/root/lib/Range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,7 @@ export default class Range<T = never> implements Iterable<T> {
return res;
}

sum(
// Warning: ValueScript has a bug where typing the `this` parameter causes it to create a
// phantom regular parameter. This only works because there aren't any other parameters.
// TODO: Fix this.
this: Range<number>,
) {
sum(this: Range<number>) {
let res = 0;

for (const x of this.iterable) {
Expand All @@ -82,12 +77,7 @@ export default class Range<T = never> implements Iterable<T> {
return res;
}

bigSum(
// Warning: ValueScript has a bug where typing the `this` parameter causes it to create a
// phantom regular parameter. This only works because there aren't any other parameters.
// TODO: Fix this.
this: Range<bigint>,
) {
bigSum(this: Range<bigint>) {
let res = 0n;

for (const x of this.iterable) {
Expand All @@ -107,12 +97,7 @@ export default class Range<T = never> implements Iterable<T> {
return res;
}

bigProduct(
// Warning: ValueScript has a bug where typing the `this` parameter causes it to create a
// phantom regular parameter. This only works because there aren't any other parameters.
// TODO: Fix this.
this: Range<bigint>,
) {
bigProduct(this: Range<bigint>) {
let res = 1n;

for (const x of this.iterable) {
Expand Down

0 comments on commit 2952d69

Please sign in to comment.