From 82b4de8ccbb701ad3404d6d8eb43dc79e3b2737f Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 3 Sep 2023 15:51:39 +0300 Subject: [PATCH 01/56] wip --- libs/tree-sitter-wing/grammar.js | 2 +- .../corpus/statements/class_and_resource.txt | 21 +- libs/wingc/src/ast.rs | 29 +- libs/wingc/src/closure_transform.rs | 9 +- libs/wingc/src/fold.rs | 10 +- libs/wingc/src/jsify.rs | 10 +- libs/wingc/src/lsp/hover.rs | 8 +- libs/wingc/src/parser.rs | 30 +- libs/wingc/src/type_check.rs | 1463 +++++++++-------- libs/wingc/src/visit.rs | 8 +- libs/wingc/src/visit_context.rs | 8 +- 11 files changed, 878 insertions(+), 720 deletions(-) diff --git a/libs/tree-sitter-wing/grammar.js b/libs/tree-sitter-wing/grammar.js index eb0f96f0d4c..563ba74e62d 100644 --- a/libs/tree-sitter-wing/grammar.js +++ b/libs/tree-sitter-wing/grammar.js @@ -529,7 +529,7 @@ module.exports = grammar({ async_modifier: ($) => "async", - access_modifier: ($) => choice("public", "private", "protected"), + access_modifier: ($) => choice("pub", "protected"), variadic: ($) => "...", diff --git a/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt b/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt index d150b03d7c0..165ed091e4f 100644 --- a/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt +++ b/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt @@ -74,12 +74,14 @@ class A { inflight init() {} preflight_func() {} async preflight_func() {} - public preflight_func2() {} + pub preflight_func2() {} inflight inflight_func() {} - public inflight inflight_func2(): num {} + pub inflight inflight_func2(): num {} + protected inflight inflight_func3(): num {} pf_member: str; inflight if_member: str; - public inflight var if_member2: str; + pub inflight var if_member2: str; + protected inflight var if_member3: str; static inflight inflight_field: num; static inflight inflight_method() {} } @@ -123,6 +125,13 @@ class A { parameter_list: (parameter_list) type: (builtin_type) block: (block)) + (inflight_method_definition + access_modifier: (access_modifier) + phase_modifier: (inflight_specifier) + name: (identifier) + parameter_list: (parameter_list) + type: (builtin_type) + block: (block)) (class_field name: (identifier) type: (builtin_type)) @@ -136,6 +145,12 @@ class A { reassignable: (reassignable) name: (identifier) type: (builtin_type)) + (class_field + access_modifier: (access_modifier) + phase_modifier: (inflight_specifier) + reassignable: (reassignable) + name: (identifier) + type: (builtin_type)) (class_field static: (static) phase_modifier: (inflight_specifier) diff --git a/libs/wingc/src/ast.rs b/libs/wingc/src/ast.rs index 18ea51bc429..fc92704aa73 100644 --- a/libs/wingc/src/ast.rs +++ b/libs/wingc/src/ast.rs @@ -297,6 +297,8 @@ pub struct FunctionDefinition { pub signature: FunctionSignature, /// Whether this function is static or not. In case of a closure, this is always true. pub is_static: bool, + /// Function's access modifier. In case of a closure, this is always public. + pub access_modifier: AccessModifier, pub span: WingSpan, } @@ -425,6 +427,16 @@ pub enum BringSource { WingFile(Symbol), } +#[derive(Debug)] +pub struct IfLet { + pub reassignable: bool, + pub var_name: Symbol, + pub value: Expr, + pub statements: Scope, + pub elif_statements: Vec, + pub else_statements: Option, +} + #[derive(Debug)] pub enum StmtKind { Bring { @@ -449,14 +461,7 @@ pub enum StmtKind { condition: Expr, statements: Scope, }, - IfLet { - reassignable: bool, - var_name: Symbol, - value: Expr, - statements: Scope, - elif_statements: Vec, - else_statements: Option, - }, + IfLet(IfLet), If { condition: Expr, statements: Scope, @@ -505,6 +510,14 @@ pub struct ClassField { pub reassignable: bool, pub phase: Phase, pub is_static: bool, + pub access_modifier: AccessModifier, +} + +#[derive(Debug)] +pub enum AccessModifier { + Private, + Public, + Protected, } #[derive(Debug)] diff --git a/libs/wingc/src/closure_transform.rs b/libs/wingc/src/closure_transform.rs index 34b1516c220..8f4425a2925 100644 --- a/libs/wingc/src/closure_transform.rs +++ b/libs/wingc/src/closure_transform.rs @@ -2,9 +2,9 @@ use indexmap::IndexMap; use crate::{ ast::{ - ArgList, CalleeKind, Class, ClassField, Expr, ExprKind, FunctionBody, FunctionDefinition, FunctionParameter, - FunctionSignature, Literal, NewExpr, Phase, Reference, Scope, Stmt, StmtKind, Symbol, TypeAnnotation, - TypeAnnotationKind, UserDefinedType, + AccessModifier, ArgList, CalleeKind, Class, ClassField, Expr, ExprKind, FunctionBody, FunctionDefinition, + FunctionParameter, FunctionSignature, Literal, NewExpr, Phase, Reference, Scope, Stmt, StmtKind, Symbol, + TypeAnnotation, TypeAnnotationKind, UserDefinedType, }, diagnostic::WingSpan, fold::{self, Fold}, @@ -180,6 +180,7 @@ impl Fold for ClosureTransformer { // Anonymous functions are always static -- since the function code is now an instance method on a class, // we need to set this to false. is_static: false, + access_modifier: AccessModifier::Public, }; // class_init_body := @@ -271,6 +272,7 @@ impl Fold for ClosureTransformer { is_static: true, body: FunctionBody::Statements(Scope::new(class_init_body, WingSpan::for_file(file_id))), span: WingSpan::for_file(file_id), + access_modifier: AccessModifier::Public, }, fields: class_fields, implements: vec![], @@ -289,6 +291,7 @@ impl Fold for ClosureTransformer { is_static: false, body: FunctionBody::Statements(Scope::new(vec![], WingSpan::for_file(file_id))), span: WingSpan::for_file(file_id), + access_modifier: AccessModifier::Public, }, }), idx: self.nearest_stmt_idx, diff --git a/libs/wingc/src/fold.rs b/libs/wingc/src/fold.rs index 788370cac36..172d30e10e9 100644 --- a/libs/wingc/src/fold.rs +++ b/libs/wingc/src/fold.rs @@ -1,7 +1,7 @@ use crate::{ ast::{ ArgList, BringSource, CalleeKind, CatchBlock, Class, ClassField, ElifBlock, ElifLetBlock, Expr, ExprKind, - FunctionBody, FunctionDefinition, FunctionParameter, FunctionSignature, Interface, InterpolatedString, + FunctionBody, FunctionDefinition, FunctionParameter, FunctionSignature, IfLet, Interface, InterpolatedString, InterpolatedStringPart, Literal, NewExpr, Reference, Scope, Stmt, StmtKind, StructField, Symbol, TypeAnnotation, TypeAnnotationKind, UserDefinedType, }, @@ -113,14 +113,14 @@ where condition: f.fold_expr(condition), statements: f.fold_scope(statements), }, - StmtKind::IfLet { + StmtKind::IfLet(IfLet { value, statements, reassignable, var_name, elif_statements, else_statements, - } => StmtKind::IfLet { + }) => StmtKind::IfLet(IfLet { value: f.fold_expr(value), statements: f.fold_scope(statements), reassignable, @@ -135,7 +135,7 @@ where }) .collect(), else_statements: else_statements.map(|statements| f.fold_scope(statements)), - }, + }), StmtKind::If { condition, statements, @@ -232,6 +232,7 @@ where reassignable: node.reassignable, phase: node.phase, is_static: node.is_static, + access_modifier: node.access_modifier, } } @@ -407,6 +408,7 @@ where signature: f.fold_function_signature(node.signature), is_static: node.is_static, span: node.span, + access_modifier: node.access_modifier, } } diff --git a/libs/wingc/src/jsify.rs b/libs/wingc/src/jsify.rs index eaef10f1df2..b5014f4f504 100644 --- a/libs/wingc/src/jsify.rs +++ b/libs/wingc/src/jsify.rs @@ -11,8 +11,8 @@ use std::{borrow::Borrow, cell::RefCell, cmp::Ordering, vec}; use crate::{ ast::{ ArgList, BinaryOperator, BringSource, CalleeKind, Class as AstClass, ElifLetBlock, Expr, ExprKind, FunctionBody, - FunctionDefinition, InterpolatedStringPart, Literal, NewExpr, Phase, Reference, Scope, Stmt, StmtKind, StructField, - Symbol, TypeAnnotationKind, UnaryOperator, UserDefinedType, + FunctionDefinition, IfLet, InterpolatedStringPart, Literal, NewExpr, Phase, Reference, Scope, Stmt, StmtKind, + StructField, Symbol, TypeAnnotationKind, UnaryOperator, UserDefinedType, }, comp_ctx::{CompilationContext, CompilationPhase}, dbg_panic, debug, @@ -916,14 +916,14 @@ impl<'a> JSifier<'a> { } StmtKind::Break => CodeMaker::one_line("break;"), StmtKind::Continue => CodeMaker::one_line("continue;"), - StmtKind::IfLet { + StmtKind::IfLet(IfLet { reassignable, value, statements, var_name, elif_statements, else_statements, - } => { + }) => { let mut code = CodeMaker::default(); // To enable shadowing variables in if let statements, the following does some scope trickery // take for example the following wing code: @@ -1635,7 +1635,7 @@ fn get_public_symbols(scope: &Scope) -> Vec { StmtKind::Let { .. } => {} StmtKind::ForLoop { .. } => {} StmtKind::While { .. } => {} - StmtKind::IfLet { .. } => {} + StmtKind::IfLet(IfLet { .. }) => {} StmtKind::If { .. } => {} StmtKind::Break => {} StmtKind::Continue => {} diff --git a/libs/wingc/src/lsp/hover.rs b/libs/wingc/src/lsp/hover.rs index 08b0df20111..8e61fb9240f 100644 --- a/libs/wingc/src/lsp/hover.rs +++ b/libs/wingc/src/lsp/hover.rs @@ -1,6 +1,6 @@ use crate::ast::{ - CalleeKind, Class, Expr, ExprKind, FunctionBody, FunctionDefinition, Phase, Reference, Scope, Stmt, StmtKind, Symbol, - UserDefinedType, + CalleeKind, Class, Expr, ExprKind, FunctionBody, FunctionDefinition, IfLet, Phase, Reference, Scope, Stmt, StmtKind, + Symbol, UserDefinedType, }; use crate::diagnostic::WingSpan; use crate::docs::Documented; @@ -162,14 +162,14 @@ impl<'a> Visit<'a> for HoverVisitor<'a> { self.visit_scope(finally_statements); } } - StmtKind::IfLet { + StmtKind::IfLet(IfLet { var_name, value, statements, reassignable: _, elif_statements, else_statements, - } => { + }) => { self.with_scope(statements, |v| { v.visit_symbol(var_name); }); diff --git a/libs/wingc/src/parser.rs b/libs/wingc/src/parser.rs index 10b34e97274..5c829103f84 100644 --- a/libs/wingc/src/parser.rs +++ b/libs/wingc/src/parser.rs @@ -8,10 +8,10 @@ use tree_sitter::Node; use tree_sitter_traversal::{traverse, Order}; use crate::ast::{ - ArgList, BinaryOperator, BringSource, CalleeKind, CatchBlock, Class, ClassField, ElifBlock, ElifLetBlock, Expr, - ExprKind, FunctionBody, FunctionDefinition, FunctionParameter, FunctionSignature, Interface, InterpolatedString, - InterpolatedStringPart, Literal, NewExpr, Phase, Reference, Scope, Stmt, StmtKind, StructField, Symbol, - TypeAnnotation, TypeAnnotationKind, UnaryOperator, UserDefinedType, + AccessModifier, ArgList, BinaryOperator, BringSource, CalleeKind, CatchBlock, Class, ClassField, ElifBlock, + ElifLetBlock, Expr, ExprKind, FunctionBody, FunctionDefinition, FunctionParameter, FunctionSignature, IfLet, + Interface, InterpolatedString, InterpolatedStringPart, Literal, NewExpr, Phase, Reference, Scope, Stmt, StmtKind, + StructField, Symbol, TypeAnnotation, TypeAnnotationKind, UnaryOperator, UserDefinedType, }; use crate::comp_ctx::{CompilationContext, CompilationPhase}; use crate::diagnostic::{report_diagnostic, Diagnostic, DiagnosticResult, WingSpan}; @@ -595,14 +595,14 @@ impl<'s> Parser<'s> { } else { None }; - Ok(StmtKind::IfLet { + Ok(StmtKind::IfLet(IfLet { var_name: name, reassignable, value, statements: if_block, elif_statements: elif_vec, else_statements: else_block, - }) + })) } fn build_if_statement(&self, statement_node: &Node, phase: Phase) -> DiagnosticResult { @@ -876,6 +876,7 @@ impl<'s> Parser<'s> { reassignable: class_element.child_by_field_name("reassignable").is_some(), is_static, phase, + access_modifier: self.build_access_modifier(class_element.child_by_field_name("access_modifier"))?, }) } "initializer" => { @@ -928,6 +929,7 @@ impl<'s> Parser<'s> { }, is_static: false, span: self.node_span(&class_element), + access_modifier: AccessModifier::Public, }) } else { initializer = Some(FunctionDefinition { @@ -942,6 +944,7 @@ impl<'s> Parser<'s> { phase: Phase::Preflight, }, span: self.node_span(&class_element), + access_modifier: AccessModifier::Public, }) } } @@ -985,6 +988,7 @@ impl<'s> Parser<'s> { body: FunctionBody::Statements(Scope::new(vec![], WingSpan::default())), is_static: false, span: WingSpan::default(), + access_modifier: AccessModifier::Public, }, }; @@ -1009,6 +1013,7 @@ impl<'s> Parser<'s> { body: FunctionBody::Statements(Scope::new(vec![], WingSpan::default())), is_static: false, span: WingSpan::default(), + access_modifier: AccessModifier::Public, }, }; @@ -1200,6 +1205,7 @@ impl<'s> Parser<'s> { signature, is_static, span: self.node_span(func_def_node), + access_modifier: self.build_access_modifier(func_def_node.child_by_field_name("access_modifier"))?, }) } @@ -1272,6 +1278,17 @@ impl<'s> Parser<'s> { } } + fn build_access_modifier(&self, am_node: Option) -> DiagnosticResult { + match am_node { + Some(am_node) => match self.node_text(&am_node) { + "pub" => Ok(AccessModifier::Public), + "protected" => Ok(AccessModifier::Protected), + other => self.with_error(format!("Unknown access modifier {other}"), &am_node), + }, + None => Ok(AccessModifier::Private), + } + } + fn build_type_annotation(&self, type_node: Option, phase: Phase) -> DiagnosticResult { let type_node = &match type_node { Some(node) => node, @@ -2081,6 +2098,7 @@ impl<'s> Parser<'s> { }, is_static: true, span: statements_span.clone(), + access_modifier: AccessModifier::Public, }), statements_span.clone(), ); diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index e3052f3f921..b4270663a52 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -4,7 +4,9 @@ pub(crate) mod jsii_importer; pub mod lifts; pub mod symbol_env; -use crate::ast::{self, BringSource, CalleeKind, ClassField, ExprId, FunctionDefinition, NewExpr, TypeAnnotationKind}; +use crate::ast::{ + self, BringSource, CalleeKind, ClassField, ExprId, FunctionDefinition, IfLet, NewExpr, TypeAnnotationKind, +}; use crate::ast::{ ArgList, BinaryOperator, Class as AstClass, Expr, ExprKind, FunctionBody, FunctionParameter as AstFunctionParameter, Interface as AstInterface, InterpolatedStringPart, Literal, Phase, Reference, Scope, Spanned, Stmt, StmtKind, Symbol, @@ -13,6 +15,7 @@ use crate::ast::{ use crate::comp_ctx::{CompilationContext, CompilationPhase}; use crate::diagnostic::{report_diagnostic, Diagnostic, TypeError, WingSpan}; use crate::docs::Docs; +use crate::visit_context::{VisitContext, VisitorWithContext}; use crate::visit_types::{VisitType, VisitTypeMut}; use crate::{ dbg_panic, debug, WINGSDK_ARRAY, WINGSDK_ASSEMBLY_NAME, WINGSDK_BRINGABLE_MODULES, WINGSDK_DURATION, WINGSDK_JSON, @@ -1604,13 +1607,9 @@ pub struct TypeChecker<'a> { /// The JSII type system jsii_types: &'a mut TypeSystem, - // Nesting level within JSON literals, a value larger than 0 means we're currently in a JSON literal - in_json: u64, - is_in_mut_json: bool, - /// Index of the current statement being type checked within the current scope - statement_idx: usize, + ctx: VisitContext, } impl<'a> TypeChecker<'a> { @@ -1626,9 +1625,8 @@ impl<'a> TypeChecker<'a> { jsii_types, source_path, jsii_imports, - in_json: 0, is_in_mut_json: false, - statement_idx: 0, + ctx: VisitContext::new(), } } @@ -1867,7 +1865,7 @@ impl<'a> TypeChecker<'a> { } = new_expr; // Type check everything let class_type = self - .resolve_user_defined_type(class, env, self.statement_idx) + .resolve_user_defined_type(class, env, self.ctx.current_stmt_idx()) .unwrap_or_else(|e| self.type_error(e)); let obj_scope_type = obj_scope.as_ref().map(|x| self.type_check_exp(x, env).0); let obj_id_type = obj_id.as_ref().map(|x| self.type_check_exp(x, env).0); @@ -1949,7 +1947,7 @@ impl<'a> TypeChecker<'a> { let obj_scope_type = if obj_scope_type.is_none() { // If this returns None, this means we're instantiating a preflight object in the global scope, which is valid env - .lookup(&"this".into(), Some(self.statement_idx)) + .lookup(&"this".into(), Some(self.ctx.current_stmt_idx())) .map(|v| v.as_variable().expect("Expected \"this\" to be a variable").type_) } else { // If this is a non-standard preflight class, make sure the object's scope isn't explicitly set (using the `in` keywords) @@ -2124,7 +2122,7 @@ impl<'a> TypeChecker<'a> { } }; (container_type, element_type) - } else if self.in_json > 0 { + } else if self.ctx.in_json() { let json_data = JsonData { expression_id: exp.id, kind: JsonDataKind::List(vec![]), @@ -2150,7 +2148,7 @@ impl<'a> TypeChecker<'a> { } } - if self.in_json == 0 { + if !self.ctx.in_json() { // If we're not in a Json literal, validate the type of each element self.validate_type(t, element_type, item); element_type = self.types.maybe_unwrap_inference(element_type); @@ -2267,7 +2265,7 @@ impl<'a> TypeChecker<'a> { // Verify that no unexpected fields are present for (name, _t) in field_types.iter() { - if st.env.lookup(name, Some(self.statement_idx)).is_none() { + if st.env.lookup(name, Some(self.ctx.current_stmt_idx())).is_none() { self.spanned_error(exp, format!("\"{}\" is not a field of \"{}\"", name.name, st.name.name)); } } @@ -2279,12 +2277,12 @@ impl<'a> TypeChecker<'a> { self.is_in_mut_json = true; } - self.in_json += 1; + self.ctx.push_json(); let (known_type, _) = self.type_check_exp(&element, env); - self.in_json -= 1; + self.ctx.pop_json(); // When we are no longer in a Json literal, we reset the is_in_mut_json flag - if self.in_json == 0 { + if !self.ctx.in_json() { self.is_in_mut_json = false; } @@ -2507,7 +2505,7 @@ impl<'a> TypeChecker<'a> { false, true, func_def.signature.phase, - self.statement_idx, + self.ctx.current_stmt_idx(), )); self.add_arguments_to_env(&func_def.signature.parameters, &sig, &mut function_env); @@ -2878,7 +2876,7 @@ impl<'a> TypeChecker<'a> { self.types.add_type(Type::Function(sig)) } TypeAnnotationKind::UserDefined(user_defined_type) => self - .resolve_user_defined_type(user_defined_type, env, self.statement_idx) + .resolve_user_defined_type(user_defined_type, env, self.ctx.current_stmt_idx()) .unwrap_or_else(|e| self.type_error(e)), TypeAnnotationKind::Array(v) => { let value_type = self.resolve_type_annotation(v, env); @@ -2942,166 +2940,33 @@ impl<'a> TypeChecker<'a> { named_args: named_arg_types, } } + fn type_check_statement(&mut self, stmt: &Stmt, env: &mut SymbolEnv) { CompilationContext::set(CompilationPhase::TypeChecking, &stmt.span); - // Set the current statement index for symbol lookup checks. We can safely assume we're - // not overwriting the current statement index because `type_check_statement` is never - // recursively called (we use a breadth-first traversal of the AST statements). - self.statement_idx = stmt.idx; - - match &stmt.kind { + // Set the current statement index for symbol lookup checks. + self.with_stmt(stmt.idx, |tc| match &stmt.kind { StmtKind::Let { reassignable, var_name, initial_value, type_, } => { - let explicit_type = type_.as_ref().map(|t| self.resolve_type_annotation(t, env)); - let (mut inferred_type, _) = self.type_check_exp(initial_value, env); - if inferred_type.is_void() { - self.spanned_error( - var_name, - format!("Cannot assign expression of type \"{}\" to a variable", inferred_type), - ); - } - if explicit_type.is_none() && inferred_type.is_nil() { - self.spanned_error( - initial_value, - "Cannot assign nil value to variables without explicit optional type", - ); - } - if let Some(explicit_type) = explicit_type { - self.validate_type(inferred_type, explicit_type, initial_value); - let final_type = if !*reassignable && explicit_type.is_json() && inferred_type.is_json() { - // If both types are Json, use the inferred type in case it has more information - inferred_type - } else { - explicit_type - }; - match env.define( - var_name, - SymbolKind::make_free_variable(var_name.clone(), final_type, *reassignable, env.phase), - StatementIdx::Index(stmt.idx), - ) { - Err(type_error) => { - self.type_error(type_error); - } - _ => {} - }; - } else { - if *reassignable && inferred_type.is_json() { - if let Type::Json(Some(_)) = *inferred_type { - // We do not have the required analysis to know the type of the Json data after reassignment - inferred_type = self.types.json(); - } - } - match env.define( - var_name, - SymbolKind::make_free_variable(var_name.clone(), inferred_type, *reassignable, env.phase), - StatementIdx::Index(stmt.idx), - ) { - Err(type_error) => { - self.type_error(type_error); - } - _ => {} - }; - } + tc.type_check_let(type_, env, initial_value, var_name, reassignable, stmt); } StmtKind::ForLoop { iterator, iterable, statements, } => { - // TODO: Expression must be iterable - let (exp_type, _) = self.type_check_exp(iterable, env); - - if !exp_type.is_iterable() { - self.spanned_error(iterable, format!("Unable to iterate over \"{}\"", &exp_type)); - } - - let iterator_type = match &*exp_type { - // These are builtin iterables that have a clear/direct iterable type - Type::Array(t) => *t, - Type::Set(t) => *t, - Type::MutArray(t) => *t, - Type::MutSet(t) => *t, - Type::Anything => exp_type, - _t => self.types.error(), - }; - - let mut scope_env = self.types.add_symbol_env(SymbolEnv::new( - Some(env.get_ref()), - env.return_type, - false, - false, - env.phase, - stmt.idx, - )); - match scope_env.define( - &iterator, - SymbolKind::make_free_variable(iterator.clone(), iterator_type, false, env.phase), - StatementIdx::Top, - ) { - Err(type_error) => { - self.type_error(type_error); - } - _ => {} - }; - self.types.set_scope_env(statements, scope_env); - - self.inner_scopes.push(statements); + tc.type_check_for_loop(iterable, env, stmt, iterator, statements); } StmtKind::While { condition, statements } => { - let (cond_type, _) = self.type_check_exp(condition, env); - self.validate_type(cond_type, self.types.bool(), condition); - - let scope_env = self.types.add_symbol_env(SymbolEnv::new( - Some(env.get_ref()), - env.return_type, - false, - false, - env.phase, - stmt.idx, - )); - self.types.set_scope_env(statements, scope_env); - - self.inner_scopes.push(statements); + tc.type_check_while(condition, env, stmt, statements); } StmtKind::Break | StmtKind::Continue => {} - StmtKind::IfLet { - value, - statements, - reassignable, - var_name, - elif_statements, - else_statements, - } => { - self.type_check_if_let_statement(value, statements, reassignable, var_name, stmt, env); - - for elif_scope in elif_statements { - self.type_check_if_let_statement( - &elif_scope.value, - &elif_scope.statements, - &elif_scope.reassignable, - &elif_scope.var_name, - stmt, - env, - ); - } - - if let Some(else_scope) = else_statements { - let else_scope_env = self.types.add_symbol_env(SymbolEnv::new( - Some(env.get_ref()), - env.return_type, - false, - false, - env.phase, - stmt.idx, - )); - self.types.set_scope_env(else_scope, else_scope_env); - self.inner_scopes.push(else_scope); - } + StmtKind::IfLet(iflet) => { + tc.type_check_iflet(env, stmt, iflet); } StmtKind::If { condition, @@ -3109,122 +2974,19 @@ impl<'a> TypeChecker<'a> { elif_statements, else_statements, } => { - self.type_check_if_statement(condition, statements, stmt, env); - - for elif_scope in elif_statements { - self.type_check_if_statement(&elif_scope.condition, &elif_scope.statements, stmt, env); - } - - if let Some(else_scope) = else_statements { - let else_scope_env = self.types.add_symbol_env(SymbolEnv::new( - Some(env.get_ref()), - env.return_type, - false, - false, - env.phase, - stmt.idx, - )); - self.types.set_scope_env(else_scope, else_scope_env); - self.inner_scopes.push(else_scope); - } + tc.type_check_if(condition, statements, stmt, env, elif_statements, else_statements); } StmtKind::Expression(e) => { - self.type_check_exp(e, env); + tc.type_check_exp(e, env); } StmtKind::Assignment { variable, value } => { - let (exp_type, _) = self.type_check_exp(value, env); - - // TODO: we need to verify that if this variable is defined in a parent environment (i.e. - // being captured) it cannot be reassigned: https://github.com/winglang/wing/issues/3069 - - let (var, var_phase) = self.resolve_reference(&variable, env); - - if !var.type_.is_unresolved() && !var.reassignable { - self.spanned_error(variable, "Variable is not reassignable".to_string()); - } else if var_phase == Phase::Preflight && env.phase == Phase::Inflight { - self.spanned_error(stmt, "Variable cannot be reassigned from inflight".to_string()); - } - - self.validate_type(exp_type, var.type_, value); + tc.type_check_assignment(value, env, variable, stmt); } StmtKind::Bring { source, identifier } => { - // library_name is the name of the library we are importing from the JSII world - let library_name: String; - // namespace_filter describes what types we are importing from the library - // e.g. [] means we are importing everything from `mylib` - // e.g. ["ns1", "ns2"] means we are importing everything from `mylib.ns1.ns2` - let namespace_filter: Vec; - // alias is the symbol we are giving to the imported library or namespace - let alias: &Symbol; - - match &source { - BringSource::BuiltinModule(name) => { - if WINGSDK_BRINGABLE_MODULES.contains(&name.name.as_str()) { - library_name = WINGSDK_ASSEMBLY_NAME.to_string(); - namespace_filter = vec![name.name.clone()]; - alias = identifier.as_ref().unwrap_or(&name); - } else if name.name.as_str() == WINGSDK_STD_MODULE { - self.spanned_error(stmt, format!("Redundant bring of \"{}\"", WINGSDK_STD_MODULE)); - return; - } else { - self.spanned_error(stmt, format!("\"{}\" is not a built-in module", name)); - return; - } - } - BringSource::JsiiModule(name) => { - library_name = name.name.to_string(); - // no namespace filter (we only support importing entire libraries at the moment) - namespace_filter = vec![]; - alias = identifier.as_ref().unwrap(); - } - BringSource::WingFile(name) => { - let (brought_env, is_bringable) = match self.types.source_file_envs.get(Utf8Path::new(&name.name)) { - Some((env, is_bringable)) => (*env, *is_bringable), - None => { - self.spanned_error( - stmt, - format!("Could not type check \"{}\" due to cyclic bring statements", name), - ); - return; - } - }; - if !is_bringable { - self.spanned_error( - stmt, - format!( - "Cannot bring \"{}\" - modules with statements besides classes, interfaces, enums, and structs cannot be brought", - name - ), - ); - return; - } - let ns = self.types.add_namespace(Namespace { - name: name.name.to_string(), - env: SymbolEnv::new( - Some(brought_env.get_ref()), - brought_env.return_type, - false, - false, - brought_env.phase, - 0, - ), - loaded: true, - }); - if let Err(e) = env.define( - identifier.as_ref().unwrap(), - SymbolKind::Namespace(ns), - StatementIdx::Top, - ) { - self.type_error(e); - } - return; - } - } - - self.add_module_to_env(env, library_name, namespace_filter, alias, Some(&stmt)); + tc.type_check_bring(source, identifier, stmt, env); } StmtKind::Scope(scope) => { - let scope_env = self.types.add_symbol_env(SymbolEnv::new( + let scope_env = tc.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), env.return_type, false, @@ -3232,469 +2994,802 @@ impl<'a> TypeChecker<'a> { env.phase, stmt.idx, )); - self.types.set_scope_env(scope, scope_env); - self.inner_scopes.push(scope) + tc.types.set_scope_env(scope, scope_env); + tc.inner_scopes.push(scope) } StmtKind::Throw(exp) => { - let (exp_type, _) = self.type_check_exp(exp, env); - self.validate_type(exp_type, self.types.string(), exp); + tc.type_check_throw(exp, env); } StmtKind::Return(exp) => { - let return_type_inferred = self.update_known_inferences(&mut env.return_type, &stmt.span); - if let Some(return_expression) = exp { - let (return_type, _) = self.type_check_exp(return_expression, env); - if !env.return_type.is_void() { - self.validate_type(return_type, env.return_type, return_expression); - } else if env.is_in_function() { - if return_type_inferred { - self.spanned_error(stmt, "Unexpected return value from void function"); - } else { - self.spanned_error( - stmt, - "Unexpected return value from void function. Return type annotations are required for methods.", - ); - } - } else { - self.spanned_error(stmt, "Return statement outside of function cannot return a value"); - } - } else { - self.validate_type(self.types.void(), env.return_type, stmt); - } - - if let Type::Json(d) = &mut *env.return_type { - // We do not have the required analysis to know the type of the Json data after return - if d.is_some() { - d.take(); - } - } + tc.type_check_return(env, stmt, exp); } - StmtKind::Class(AstClass { - name, - fields, - methods, - parent, - implements, - initializer, - phase, - inflight_initializer, - }) => { - // preflight classes cannot be declared inside an inflight scope - // (the other way is okay) - if env.phase == Phase::Inflight && *phase == Phase::Preflight { - self.spanned_error(stmt, format!("Cannot declare a {} class in {} scope", phase, env.phase)); - } - // Verify parent is a known class and get their env - let (parent_class, parent_class_env) = self.extract_parent_class(parent.as_ref(), *phase, name, env); + StmtKind::Class(ast_class) => { + tc.type_check_class(env, stmt, ast_class); + } + StmtKind::Interface(AstInterface { name, methods, extends }) => { + tc.type_check_interface(env, stmt, extends, name, methods); + } + StmtKind::Struct { name, extends, fields } => { + tc.type_check_struct(stmt, fields, env, extends, name); + } + StmtKind::Enum { name, values } => { + tc.type_check_enum(name, values, env); + } + StmtKind::TryCatch { + try_statements, + catch_block, + finally_statements, + } => { + tc.type_check_try_catch(env, stmt, try_statements, catch_block, finally_statements); + } + StmtKind::CompilerDebugEnv => { + println!("[symbol environment at {}]", stmt.span); + println!("{}", env); + } + StmtKind::SuperConstructor { arg_list } => { + tc.type_check_arg_list(arg_list, env); + } + }); + } - // Create environment representing this class, for now it'll be empty just so we can support referencing ourselves from the class definition. - let dummy_env = SymbolEnv::new(None, self.types.void(), false, false, env.phase, stmt.idx); + fn type_check_try_catch( + &mut self, + env: &mut SymbolEnv, + stmt: &Stmt, + try_statements: &Scope, + catch_block: &Option, + finally_statements: &Option, + ) { + // Create a new environment for the try block + let try_env = self.types.add_symbol_env(SymbolEnv::new( + Some(env.get_ref()), + env.return_type, + false, + false, + env.phase, + stmt.idx, + )); + self.types.set_scope_env(try_statements, try_env); + self.inner_scopes.push(try_statements); + + // Create a new environment for the catch block + if let Some(catch_block) = catch_block { + let mut catch_env = self.types.add_symbol_env(SymbolEnv::new( + Some(env.get_ref()), + env.return_type, + false, + false, + env.phase, + stmt.idx, + )); - let impl_interfaces = implements - .iter() - .filter_map(|i| { - let t = self - .resolve_user_defined_type(i, env, stmt.idx) - .unwrap_or_else(|e| self.type_error(e)); - if t.as_interface().is_some() { - Some(t) - } else { - self.spanned_error(i, format!("Expected an interface, instead found type \"{}\"", t)); - None - } - }) - .collect::>(); - - // Create the resource/class type and add it to the current environment (so class implementation can reference itself) - let class_spec = Class { - name: name.clone(), - fqn: None, - env: dummy_env, - parent: parent_class, - implements: impl_interfaces.clone(), - is_abstract: false, - phase: *phase, - type_parameters: None, // TODO no way to have generic args in wing yet - docs: Docs::default(), - std_construct_args: *phase == Phase::Preflight, - lifts: None, - }; - let mut class_type = self.types.add_type(Type::Class(class_spec)); - match env.define(name, SymbolKind::Type(class_type), StatementIdx::Top) { + // Add the exception variable to the catch block + if let Some(exception_var) = &catch_block.exception_var { + match catch_env.define( + exception_var, + SymbolKind::make_free_variable(exception_var.clone(), self.types.string(), false, env.phase), + StatementIdx::Top, + ) { Err(type_error) => { self.type_error(type_error); } _ => {} - }; - - // Create a the real class environment to be filled with the class AST types - let mut class_env = SymbolEnv::new(parent_class_env, self.types.void(), false, false, env.phase, stmt.idx); - - // Add fields to the class env - for field in fields.iter() { - let field_type = self.resolve_type_annotation(&field.member_type, env); - match class_env.define( - &field.name, - SymbolKind::make_member_variable( - field.name.clone(), - field_type, - field.reassignable, - field.is_static, - field.phase, - None, - ), - StatementIdx::Top, - ) { - Err(type_error) => { - self.type_error(type_error); - } - _ => {} - }; } + } + self.types.set_scope_env(&catch_block.statements, catch_env); + self.inner_scopes.push(&catch_block.statements); + } - // Add methods to the class env - for (method_name, method_def) in methods.iter() { - self.add_method_to_class_env( - &method_def.signature, - env, - if method_def.is_static { None } else { Some(class_type) }, - &mut class_env, - method_name, - ); - } + // Create a new environment for the finally block + if let Some(finally_statements) = finally_statements { + let finally_env = self.types.add_symbol_env(SymbolEnv::new( + Some(env.get_ref()), + env.return_type, + false, + false, + env.phase, + stmt.idx, + )); + self.types.set_scope_env(finally_statements, finally_env); + self.inner_scopes.push(finally_statements); + } + } - // Add the constructor to the class env - let init_symb = Symbol { - name: CLASS_INIT_NAME.into(), - span: initializer.span.clone(), - }; + fn type_check_enum(&mut self, name: &Symbol, values: &IndexSet, env: &mut SymbolEnv) { + let enum_type_ref = self.types.add_type(Type::Enum(Enum { + name: name.clone(), + values: values.clone(), + docs: Default::default(), + })); + + match env.define(name, SymbolKind::Type(enum_type_ref), StatementIdx::Top) { + Err(type_error) => { + self.type_error(type_error); + } + _ => {} + }; + } - self.add_method_to_class_env(&initializer.signature, env, None, &mut class_env, &init_symb); + fn type_check_struct( + &mut self, + stmt: &Stmt, + fields: &Vec, + env: &mut SymbolEnv, + extends: &Vec, + name: &Symbol, + ) { + // Note: structs don't have a parent environment, instead they flatten their parent's members into the struct's env. + // If we encounter an existing member with the same name and type we skip it, if the types are different we + // fail type checking. - let inflight_init_symb = Symbol { - name: CLASS_INFLIGHT_INIT_NAME.into(), - span: inflight_initializer.span.clone(), - }; + // Create an environment for the struct + let mut struct_env = SymbolEnv::new(None, self.types.void(), false, false, Phase::Independent, stmt.idx); - // Add the inflight initializer to the class env - self.add_method_to_class_env( - &inflight_initializer.signature, - env, - Some(class_type), - &mut class_env, - &inflight_init_symb, - ); + // Add fields to the struct env + for field in fields.iter() { + let field_type = self.resolve_type_annotation(&field.member_type, env); + if field_type.is_mutable() { + self.spanned_error(&field.name, "Struct fields must have immutable types"); + } + match struct_env.define( + &field.name, + SymbolKind::make_member_variable(field.name.clone(), field_type, false, false, Phase::Independent, None), + StatementIdx::Top, + ) { + Err(type_error) => { + self.type_error(type_error); + } + _ => {} + }; + } - // Replace the dummy class environment with the real one before type checking the methods - if let Some(mut_class) = class_type.as_class_mut() { - mut_class.env = class_env; + // Add members from the structs parents + let extends_types = extends + .iter() + .filter_map(|ext| { + let t = self + .resolve_user_defined_type(ext, env, stmt.idx) + .unwrap_or_else(|e| self.type_error(e)); + if t.as_struct().is_some() { + Some(t) } else { - panic!("Expected class type"); + self.spanned_error(ext, format!("Expected a struct, found type \"{}\"", t)); + None } - // let mut class_env = &mut mut_class.env; - - if let FunctionBody::Statements(scope) = &inflight_initializer.body { - self.check_class_field_initialization(&scope, fields, Phase::Inflight); - self.type_check_super_constructor_against_parent_initializer( - scope, - class_type, - &mut class_type.as_class_mut().unwrap().env, - CLASS_INFLIGHT_INIT_NAME, - ); - }; + }) + .collect::>(); - // Type check constructor - self.type_check_method(class_type, &init_symb, env, stmt.idx, initializer); + if let Err(e) = add_parent_members_to_struct_env(&extends_types, name, &mut struct_env) { + self.type_error(e); + } + match env.define( + name, + SymbolKind::Type(self.types.add_type(Type::Struct(Struct { + name: name.clone(), + extends: extends_types, + env: struct_env, + docs: Docs::default(), + }))), + StatementIdx::Top, + ) { + Err(type_error) => { + self.type_error(type_error); + } + _ => {} + }; + } - // Verify if all fields of a class/resource are initialized in the initializer. - let init_statements = match &initializer.body { - FunctionBody::Statements(s) => s, - FunctionBody::External(_) => panic!("init cannot be extern"), - }; + fn type_check_interface( + &mut self, + env: &mut SymbolEnv, + stmt: &Stmt, + extends: &Vec, + name: &Symbol, + methods: &Vec<(Symbol, ast::FunctionSignature)>, + ) { + // Create environment representing this interface, for now it'll be empty just so we can support referencing ourselves from the interface definition. + let dummy_env = SymbolEnv::new(None, self.types.void(), false, false, env.phase, stmt.idx); - self.check_class_field_initialization(&init_statements, fields, Phase::Preflight); + let extend_interfaces = extends + .iter() + .filter_map(|i| { + let t = self + .resolve_user_defined_type(i, env, stmt.idx) + .unwrap_or_else(|e| self.type_error(e)); + if t.as_interface().is_some() { + Some(t) + } else { + // The type checker resolves non-existing definitions to `any`, so we avoid duplicate errors by checking for that here + if !t.is_unresolved() { + self.spanned_error(i, format!("Expected an interface, instead found type \"{}\"", t)); + } + None + } + }) + .collect::>(); - self.type_check_super_constructor_against_parent_initializer( - init_statements, - class_type, - &mut class_type.as_class_mut().unwrap().env, - CLASS_INIT_NAME, - ); + // Create the interface type and add it to the current environment (so interface implementation can reference itself) + let interface_spec = Interface { + name: name.clone(), + docs: Docs::default(), + env: dummy_env, + extends: extend_interfaces.clone(), + }; + let mut interface_type = self.types.add_type(Type::Interface(interface_spec)); + match env.define(name, SymbolKind::Type(interface_type), StatementIdx::Top) { + Err(type_error) => { + self.type_error(type_error); + } + _ => {} + }; - // Type check the inflight initializer - self.type_check_method(class_type, &inflight_init_symb, env, stmt.idx, inflight_initializer); + // Create the real interface environment to be filled with the interface AST types + let mut interface_env = SymbolEnv::new(None, self.types.void(), false, false, env.phase, stmt.idx); - // TODO: handle member/method overrides in our env based on whatever rules we define in our spec - // https://github.com/winglang/wing/issues/1124 + // Add methods to the interface env + for (method_name, sig) in methods.iter() { + let mut method_type = self.resolve_type_annotation(&sig.to_type_annotation(), env); + // use the interface type as the function's "this" type + if let Type::Function(ref mut f) = *method_type { + f.this_type = Some(interface_type); + } else { + panic!("Expected method type to be a function"); + } - // Type check methods - for (method_name, method_def) in methods.iter() { - self.type_check_method(class_type, method_name, env, stmt.idx, method_def); + match interface_env.define( + method_name, + SymbolKind::make_member_variable(method_name.clone(), method_type, false, false, sig.phase, None), + StatementIdx::Top, + ) { + Err(type_error) => { + self.type_error(type_error); } + _ => {} + }; + } - // Check that the class satisfies all of its interfaces - for interface_type in impl_interfaces.iter() { - let interface_type = match interface_type.as_interface() { - Some(t) => t, - None => { - // No need to error here, it will be caught when `impl_interaces` was created - continue; - } - }; + // add methods from all extended interfaces to the interface env + if let Err(e) = add_parent_members_to_iface_env(&extend_interfaces, name, &mut interface_env) { + self.type_error(e); + } - // Check all methods are implemented - for (method_name, method_type) in interface_type.methods(true) { - if let Some(symbol) = &mut class_type - .as_class_mut() - .unwrap() - .env - .lookup(&method_name.as_str().into(), None) - { - let class_method_type = symbol.as_variable().expect("Expected method to be a variable").type_; - self.validate_type(class_method_type, method_type, name); - } else { - self.spanned_error( - name, - format!( - "Class \"{}\" does not implement method \"{}\" of interface \"{}\"", - name.name, method_name, interface_type.name.name - ), - ); - } - } + // Replace the dummy interface environment with the real one before type checking the methods + interface_type.as_mut_interface().unwrap().env = interface_env; + } - // Check all fields are implemented - for (field_name, field_type) in interface_type.fields(true) { - if let Some(symbol) = &mut class_type - .as_class_mut() - .unwrap() - .env - .lookup(&field_name.as_str().into(), None) - { - let class_field_type = symbol.as_variable().expect("Expected field to be a variable").type_; - self.validate_type(class_field_type, field_type, name); - } else { - self.spanned_error( - name, - format!( - "Class \"{}\" does not implement field \"{}\" of interface \"{}\"", - name.name, field_name, interface_type.name.name - ), - ); - } - } + fn type_check_class(&mut self, env: &mut SymbolEnv, stmt: &Stmt, ast_class: &AstClass) { + // preflight classes cannot be declared inside an inflight scope + // (the other way is okay) + if env.phase == Phase::Inflight && ast_class.phase == Phase::Preflight { + self.spanned_error( + stmt, + format!("Cannot declare a {} class in {} scope", ast_class.phase, env.phase), + ); + } + // Verify parent is a known class and get their env + let (parent_class, parent_class_env) = + self.extract_parent_class(ast_class.parent.as_ref(), ast_class.phase, &ast_class.name, env); + + // Create environment representing this class, for now it'll be empty just so we can support referencing ourselves from the class definition. + let dummy_env = SymbolEnv::new(None, self.types.void(), false, false, env.phase, stmt.idx); + + let impl_interfaces = ast_class + .implements + .iter() + .filter_map(|i| { + let t = self + .resolve_user_defined_type(i, env, stmt.idx) + .unwrap_or_else(|e| self.type_error(e)); + if t.as_interface().is_some() { + Some(t) + } else { + self.spanned_error(i, format!("Expected an interface, instead found type \"{}\"", t)); + None } + }) + .collect::>(); + + // Create the resource/class type and add it to the current environment (so class implementation can reference itself) + let class_spec = Class { + name: ast_class.name.clone(), + fqn: None, + env: dummy_env, + parent: parent_class, + implements: impl_interfaces.clone(), + is_abstract: false, + phase: ast_class.phase, + type_parameters: None, // TODO no way to have generic args in wing yet + docs: Docs::default(), + std_construct_args: ast_class.phase == Phase::Preflight, + lifts: None, + }; + let mut class_type = self.types.add_type(Type::Class(class_spec)); + match env.define(&ast_class.name, SymbolKind::Type(class_type), StatementIdx::Top) { + Err(type_error) => { + self.type_error(type_error); } - StmtKind::Interface(AstInterface { name, methods, extends }) => { - // Create environment representing this interface, for now it'll be empty just so we can support referencing ourselves from the interface definition. - let dummy_env = SymbolEnv::new(None, self.types.void(), false, false, env.phase, stmt.idx); + _ => {} + }; - let extend_interfaces = extends - .iter() - .filter_map(|i| { - let t = self - .resolve_user_defined_type(i, env, stmt.idx) - .unwrap_or_else(|e| self.type_error(e)); - if t.as_interface().is_some() { - Some(t) - } else { - // The type checker resolves non-existing definitions to `any`, so we avoid duplicate errors by checking for that here - if !t.is_unresolved() { - self.spanned_error(i, format!("Expected an interface, instead found type \"{}\"", t)); - } - None - } - }) - .collect::>(); + // Create a the real class environment to be filled with the class AST types + let mut class_env = SymbolEnv::new(parent_class_env, self.types.void(), false, false, env.phase, stmt.idx); + + // Add fields to the class env + for field in ast_class.fields.iter() { + let field_type = self.resolve_type_annotation(&field.member_type, env); + match class_env.define( + &field.name, + SymbolKind::make_member_variable( + field.name.clone(), + field_type, + field.reassignable, + field.is_static, + field.phase, + None, + ), + StatementIdx::Top, + ) { + Err(type_error) => { + self.type_error(type_error); + } + _ => {} + }; + } - // Create the interface type and add it to the current environment (so interface implementation can reference itself) - let interface_spec = Interface { - name: name.clone(), - docs: Docs::default(), - env: dummy_env, - extends: extend_interfaces.clone(), - }; - let mut interface_type = self.types.add_type(Type::Interface(interface_spec)); - match env.define(name, SymbolKind::Type(interface_type), StatementIdx::Top) { - Err(type_error) => { - self.type_error(type_error); - } - _ => {} - }; + // Add methods to the class env + for (method_name, method_def) in ast_class.methods.iter() { + self.add_method_to_class_env( + &method_def.signature, + env, + if method_def.is_static { None } else { Some(class_type) }, + &mut class_env, + method_name, + ); + } - // Create the real interface environment to be filled with the interface AST types - let mut interface_env = SymbolEnv::new(None, self.types.void(), false, false, env.phase, stmt.idx); + // Add the constructor to the class env + let init_symb = Symbol { + name: CLASS_INIT_NAME.into(), + span: ast_class.initializer.span.clone(), + }; - // Add methods to the interface env - for (method_name, sig) in methods.iter() { - let mut method_type = self.resolve_type_annotation(&sig.to_type_annotation(), env); - // use the interface type as the function's "this" type - if let Type::Function(ref mut f) = *method_type { - f.this_type = Some(interface_type); - } else { - panic!("Expected method type to be a function"); - } + self.add_method_to_class_env(&ast_class.initializer.signature, env, None, &mut class_env, &init_symb); - match interface_env.define( - method_name, - SymbolKind::make_member_variable(method_name.clone(), method_type, false, false, sig.phase, None), - StatementIdx::Top, - ) { - Err(type_error) => { - self.type_error(type_error); - } - _ => {} - }; - } + let inflight_init_symb = Symbol { + name: CLASS_INFLIGHT_INIT_NAME.into(), + span: ast_class.inflight_initializer.span.clone(), + }; - // add methods from all extended interfaces to the interface env - if let Err(e) = add_parent_members_to_iface_env(&extend_interfaces, name, &mut interface_env) { - self.type_error(e); + // Add the inflight initializer to the class env + self.add_method_to_class_env( + &ast_class.inflight_initializer.signature, + env, + Some(class_type), + &mut class_env, + &inflight_init_symb, + ); + + // Replace the dummy class environment with the real one before type checking the methods + if let Some(mut_class) = class_type.as_class_mut() { + mut_class.env = class_env; + } else { + panic!("Expected class type"); + } + // let mut class_env = &mut mut_class.env; + + if let FunctionBody::Statements(scope) = &ast_class.inflight_initializer.body { + self.check_class_field_initialization(&scope, &ast_class.fields, Phase::Inflight); + self.type_check_super_constructor_against_parent_initializer( + scope, + class_type, + &mut class_type.as_class_mut().unwrap().env, + CLASS_INFLIGHT_INIT_NAME, + ); + }; + + // Type check constructor + self.type_check_method(class_type, &init_symb, env, stmt.idx, &ast_class.initializer); + + // Verify if all fields of a class/resource are initialized in the initializer. + let init_statements = match &ast_class.initializer.body { + FunctionBody::Statements(s) => s, + FunctionBody::External(_) => panic!("init cannot be extern"), + }; + + self.check_class_field_initialization(&init_statements, &ast_class.fields, Phase::Preflight); + + self.type_check_super_constructor_against_parent_initializer( + init_statements, + class_type, + &mut class_type.as_class_mut().unwrap().env, + CLASS_INIT_NAME, + ); + + // Type check the inflight initializer + self.type_check_method( + class_type, + &inflight_init_symb, + env, + stmt.idx, + &ast_class.inflight_initializer, + ); + + // TODO: handle member/method overrides in our env based on whatever rules we define in our spec + // https://github.com/winglang/wing/issues/1124 + + // Type check methods + for (method_name, method_def) in ast_class.methods.iter() { + self.type_check_method(class_type, method_name, env, stmt.idx, method_def); + } + + // Check that the class satisfies all of its interfaces + for interface_type in impl_interfaces.iter() { + let interface_type = match interface_type.as_interface() { + Some(t) => t, + None => { + // No need to error here, it will be caught when `impl_interaces` was created + continue; } + }; - // Replace the dummy interface environment with the real one before type checking the methods - interface_type.as_mut_interface().unwrap().env = interface_env; - } - StmtKind::Struct { name, extends, fields } => { - // Note: structs don't have a parent environment, instead they flatten their parent's members into the struct's env. - // If we encounter an existing member with the same name and type we skip it, if the types are different we - // fail type checking. - - // Create an environment for the struct - let mut struct_env = SymbolEnv::new(None, self.types.void(), false, false, Phase::Independent, stmt.idx); - - // Add fields to the struct env - for field in fields.iter() { - let field_type = self.resolve_type_annotation(&field.member_type, env); - if field_type.is_mutable() { - self.spanned_error(&field.name, "Struct fields must have immutable types"); - } - match struct_env.define( - &field.name, - SymbolKind::make_member_variable(field.name.clone(), field_type, false, false, Phase::Independent, None), - StatementIdx::Top, - ) { - Err(type_error) => { - self.type_error(type_error); - } - _ => {} - }; + // Check all methods are implemented + for (method_name, method_type) in interface_type.methods(true) { + if let Some(symbol) = &mut class_type + .as_class_mut() + .unwrap() + .env + .lookup(&method_name.as_str().into(), None) + { + let class_method_type = symbol.as_variable().expect("Expected method to be a variable").type_; + self.validate_type(class_method_type, method_type, &ast_class.name); + } else { + self.spanned_error( + &ast_class.name, + format!( + "Class \"{}\" does not implement method \"{}\" of interface \"{}\"", + &ast_class.name, method_name, interface_type.name.name + ), + ); } + } - // Add members from the structs parents - let extends_types = extends - .iter() - .filter_map(|ext| { - let t = self - .resolve_user_defined_type(ext, env, stmt.idx) - .unwrap_or_else(|e| self.type_error(e)); - if t.as_struct().is_some() { - Some(t) - } else { - self.spanned_error(ext, format!("Expected a struct, found type \"{}\"", t)); - None - } - }) - .collect::>(); + // Check all fields are implemented + for (field_name, field_type) in interface_type.fields(true) { + if let Some(symbol) = &mut class_type + .as_class_mut() + .unwrap() + .env + .lookup(&field_name.as_str().into(), None) + { + let class_field_type = symbol.as_variable().expect("Expected field to be a variable").type_; + self.validate_type(class_field_type, field_type, &ast_class.name); + } else { + self.spanned_error( + &ast_class.name, + format!( + "Class \"{}\" does not implement field \"{}\" of interface \"{}\"", + &ast_class.name, field_name, interface_type.name.name + ), + ); + } + } + } + } - if let Err(e) = add_parent_members_to_struct_env(&extends_types, name, &mut struct_env) { - self.type_error(e); + fn type_check_return(&mut self, env: &mut SymbolEnv, stmt: &Stmt, exp: &Option) { + let return_type_inferred = self.update_known_inferences(&mut env.return_type, &stmt.span); + if let Some(return_expression) = exp { + let (return_type, _) = self.type_check_exp(return_expression, env); + if !env.return_type.is_void() { + self.validate_type(return_type, env.return_type, return_expression); + } else if env.is_in_function() { + if return_type_inferred { + self.spanned_error(stmt, "Unexpected return value from void function"); + } else { + self.spanned_error( + stmt, + "Unexpected return value from void function. Return type annotations are required for methods.", + ); } - match env.define( - name, - SymbolKind::Type(self.types.add_type(Type::Struct(Struct { - name: name.clone(), - extends: extends_types, - env: struct_env, - docs: Docs::default(), - }))), - StatementIdx::Top, - ) { - Err(type_error) => { - self.type_error(type_error); - } - _ => {} - }; + } else { + self.spanned_error(stmt, "Return statement outside of function cannot return a value"); } - StmtKind::Enum { name, values } => { - let enum_type_ref = self.types.add_type(Type::Enum(Enum { - name: name.clone(), - values: values.clone(), - docs: Default::default(), - })); + } else { + self.validate_type(self.types.void(), env.return_type, stmt); + } - match env.define(name, SymbolKind::Type(enum_type_ref), StatementIdx::Top) { - Err(type_error) => { - self.type_error(type_error); - } - _ => {} - }; + if let Type::Json(d) = &mut *env.return_type { + // We do not have the required analysis to know the type of the Json data after return + if d.is_some() { + d.take(); } - StmtKind::TryCatch { - try_statements, - catch_block, - finally_statements, - } => { - // Create a new environment for the try block - let try_env = self.types.add_symbol_env(SymbolEnv::new( - Some(env.get_ref()), - env.return_type, - false, - false, - env.phase, - stmt.idx, - )); - self.types.set_scope_env(try_statements, try_env); - self.inner_scopes.push(try_statements); - - // Create a new environment for the catch block - if let Some(catch_block) = catch_block { - let mut catch_env = self.types.add_symbol_env(SymbolEnv::new( - Some(env.get_ref()), - env.return_type, - false, - false, - env.phase, - stmt.idx, - )); + } + } - // Add the exception variable to the catch block - if let Some(exception_var) = &catch_block.exception_var { - match catch_env.define( - exception_var, - SymbolKind::make_free_variable(exception_var.clone(), self.types.string(), false, env.phase), - StatementIdx::Top, - ) { - Err(type_error) => { - self.type_error(type_error); - } - _ => {} - } + fn type_check_throw(&mut self, exp: &Expr, env: &mut SymbolEnv) { + let (exp_type, _) = self.type_check_exp(exp, env); + self.validate_type(exp_type, self.types.string(), exp); + } + + fn type_check_bring(&mut self, source: &BringSource, identifier: &Option, stmt: &Stmt, env: &mut SymbolEnv) { + let library_name: String; + let namespace_filter: Vec; + let alias: &Symbol; + match &source { + BringSource::BuiltinModule(name) => { + if WINGSDK_BRINGABLE_MODULES.contains(&name.name.as_str()) { + library_name = WINGSDK_ASSEMBLY_NAME.to_string(); + namespace_filter = vec![name.name.clone()]; + alias = identifier.as_ref().unwrap_or(&name); + } else if name.name.as_str() == WINGSDK_STD_MODULE { + self.spanned_error(stmt, format!("Redundant bring of \"{}\"", WINGSDK_STD_MODULE)); + return; + } else { + self.spanned_error(stmt, format!("\"{}\" is not a built-in module", name)); + return; + } + } + BringSource::JsiiModule(name) => { + library_name = name.name.to_string(); + // no namespace filter (we only support importing entire libraries at the moment) + namespace_filter = vec![]; + alias = identifier.as_ref().unwrap(); + } + BringSource::WingFile(name) => { + let (brought_env, is_bringable) = match self.types.source_file_envs.get(Utf8Path::new(&name.name)) { + Some((env, is_bringable)) => (*env, *is_bringable), + None => { + self.spanned_error( + stmt, + format!("Could not type check \"{}\" due to cyclic bring statements", name), + ); + return; } - self.types.set_scope_env(&catch_block.statements, catch_env); - self.inner_scopes.push(&catch_block.statements); + }; + if !is_bringable { + self.spanned_error( + stmt, + format!( + "Cannot bring \"{}\" - modules with statements besides classes, interfaces, enums, and structs cannot be brought", + name + ), + ); + return; } - - // Create a new environment for the finally block - if let Some(finally_statements) = finally_statements { - let finally_env = self.types.add_symbol_env(SymbolEnv::new( - Some(env.get_ref()), - env.return_type, + let ns = self.types.add_namespace(Namespace { + name: name.name.to_string(), + env: SymbolEnv::new( + Some(brought_env.get_ref()), + brought_env.return_type, false, false, - env.phase, - stmt.idx, - )); - self.types.set_scope_env(finally_statements, finally_env); - self.inner_scopes.push(finally_statements); + brought_env.phase, + 0, + ), + loaded: true, + }); + if let Err(e) = env.define( + identifier.as_ref().unwrap(), + SymbolKind::Namespace(ns), + StatementIdx::Top, + ) { + self.type_error(e); } + return; } - StmtKind::CompilerDebugEnv => { - println!("[symbol environment at {}]", stmt.span); - println!("{}", env); + } + self.add_module_to_env(env, library_name, namespace_filter, alias, Some(&stmt)); + // library_name is the name of the library we are importing from the JSII world + // namespace_filter describes what types we are importing from the library + // e.g. [] means we are importing everything from `mylib` + // e.g. ["ns1", "ns2"] means we are importing everything from `mylib.ns1.ns2` + // alias is the symbol we are giving to the imported library or namespace + } + + fn type_check_assignment(&mut self, value: &Expr, env: &mut SymbolEnv, variable: &Reference, stmt: &Stmt) { + let (exp_type, _) = self.type_check_exp(value, env); + + // TODO: we need to verify that if this variable is defined in a parent environment (i.e. + // being captured) it cannot be reassigned: https://github.com/winglang/wing/issues/3069 + + let (var, var_phase) = self.resolve_reference(&variable, env); + + if !var.type_.is_unresolved() && !var.reassignable { + self.spanned_error(variable, "Variable is not reassignable".to_string()); + } else if var_phase == Phase::Preflight && env.phase == Phase::Inflight { + self.spanned_error(stmt, "Variable cannot be reassigned from inflight".to_string()); + } + + self.validate_type(exp_type, var.type_, value); + } + + fn type_check_if( + &mut self, + condition: &Expr, + statements: &Scope, + stmt: &Stmt, + env: &mut SymbolEnv, + elif_statements: &Vec, + else_statements: &Option, + ) { + self.type_check_if_statement(condition, statements, stmt, env); + + for elif_scope in elif_statements { + self.type_check_if_statement(&elif_scope.condition, &elif_scope.statements, stmt, env); + } + + if let Some(else_scope) = else_statements { + let else_scope_env = self.types.add_symbol_env(SymbolEnv::new( + Some(env.get_ref()), + env.return_type, + false, + false, + env.phase, + stmt.idx, + )); + self.types.set_scope_env(else_scope, else_scope_env); + self.inner_scopes.push(else_scope); + } + } + + fn type_check_iflet(&mut self, env: &mut SymbolEnv, stmt: &Stmt, iflet: &IfLet) { + self.type_check_if_let_statement( + &iflet.value, + &iflet.statements, + &iflet.reassignable, + &iflet.var_name, + stmt, + env, + ); + + for elif_scope in &iflet.elif_statements { + self.type_check_if_let_statement( + &elif_scope.value, + &elif_scope.statements, + &elif_scope.reassignable, + &elif_scope.var_name, + stmt, + env, + ); + } + + if let Some(else_scope) = &iflet.else_statements { + let else_scope_env = self.types.add_symbol_env(SymbolEnv::new( + Some(env.get_ref()), + env.return_type, + false, + false, + env.phase, + stmt.idx, + )); + self.types.set_scope_env(else_scope, else_scope_env); + self.inner_scopes.push(else_scope); + } + } + + fn type_check_while(&mut self, condition: &Expr, env: &mut SymbolEnv, stmt: &Stmt, statements: &Scope) { + let (cond_type, _) = self.type_check_exp(condition, env); + self.validate_type(cond_type, self.types.bool(), condition); + + let scope_env = self.types.add_symbol_env(SymbolEnv::new( + Some(env.get_ref()), + env.return_type, + false, + false, + env.phase, + stmt.idx, + )); + self.types.set_scope_env(statements, scope_env); + + self.inner_scopes.push(statements); + } + + fn type_check_for_loop( + &mut self, + iterable: &Expr, + env: &mut SymbolEnv, + stmt: &Stmt, + iterator: &Symbol, + statements: &Scope, + ) { + // TODO: Expression must be iterable + let (exp_type, _) = self.type_check_exp(iterable, env); + + if !exp_type.is_iterable() { + self.spanned_error(iterable, format!("Unable to iterate over \"{}\"", &exp_type)); + } + + let iterator_type = match &*exp_type { + // These are builtin iterables that have a clear/direct iterable type + Type::Array(t) => *t, + Type::Set(t) => *t, + Type::MutArray(t) => *t, + Type::MutSet(t) => *t, + Type::Anything => exp_type, + _t => self.types.error(), + }; + + let mut scope_env = self.types.add_symbol_env(SymbolEnv::new( + Some(env.get_ref()), + env.return_type, + false, + false, + env.phase, + stmt.idx, + )); + match scope_env.define( + &iterator, + SymbolKind::make_free_variable(iterator.clone(), iterator_type, false, env.phase), + StatementIdx::Top, + ) { + Err(type_error) => { + self.type_error(type_error); } - StmtKind::SuperConstructor { arg_list } => { - self.type_check_arg_list(arg_list, env); + _ => {} + }; + self.types.set_scope_env(statements, scope_env); + + self.inner_scopes.push(statements); + } + + fn type_check_let( + &mut self, + type_: &Option, + env: &mut SymbolEnv, + initial_value: &Expr, + var_name: &Symbol, + reassignable: &bool, + stmt: &Stmt, + ) { + let explicit_type = type_.as_ref().map(|t| self.resolve_type_annotation(t, env)); + let (mut inferred_type, _) = self.type_check_exp(initial_value, env); + if inferred_type.is_void() { + self.spanned_error( + var_name, + format!("Cannot assign expression of type \"{}\" to a variable", inferred_type), + ); + } + if explicit_type.is_none() && inferred_type.is_nil() { + self.spanned_error( + initial_value, + "Cannot assign nil value to variables without explicit optional type", + ); + } + if let Some(explicit_type) = explicit_type { + self.validate_type(inferred_type, explicit_type, initial_value); + let final_type = if !*reassignable && explicit_type.is_json() && inferred_type.is_json() { + // If both types are Json, use the inferred type in case it has more information + inferred_type + } else { + explicit_type + }; + match env.define( + var_name, + SymbolKind::make_free_variable(var_name.clone(), final_type, *reassignable, env.phase), + StatementIdx::Index(stmt.idx), + ) { + Err(type_error) => { + self.type_error(type_error); + } + _ => {} + }; + } else { + if *reassignable && inferred_type.is_json() { + if let Type::Json(Some(_)) = *inferred_type { + // We do not have the required analysis to know the type of the Json data after reassignment + inferred_type = self.types.json(); + } } + match env.define( + var_name, + SymbolKind::make_free_variable(var_name.clone(), inferred_type, *reassignable, env.phase), + StatementIdx::Index(stmt.idx), + ) { + Err(type_error) => { + self.type_error(type_error); + } + _ => {} + }; } } @@ -4417,7 +4512,7 @@ impl<'a> TypeChecker<'a> { // then resolve a class named "Util" within it. This will basically be equivalent to the // `foo.Bar.baz()` case (where `baz()`) is a static method of class `Bar`. if base_udt.fields.is_empty() { - let result = env.lookup_nested_str(&base_udt.full_path_str(), Some(self.statement_idx)); + let result = env.lookup_nested_str(&base_udt.full_path_str(), Some(self.ctx.current_stmt_idx())); if let LookupResult::Found(symbol_kind, _) = result { if let SymbolKind::Namespace(_) = symbol_kind { let mut new_udt = base_udt.clone(); @@ -4427,7 +4522,7 @@ impl<'a> TypeChecker<'a> { }); return self - .resolve_user_defined_type(&new_udt, env, self.statement_idx) + .resolve_user_defined_type(&new_udt, env, self.ctx.current_stmt_idx()) .ok() .map(|_| new_udt); } @@ -4435,7 +4530,7 @@ impl<'a> TypeChecker<'a> { } self - .resolve_user_defined_type(&base_udt, env, self.statement_idx) + .resolve_user_defined_type(&base_udt, env, self.ctx.current_stmt_idx()) .ok() .map(|_| base_udt) } @@ -4443,7 +4538,7 @@ impl<'a> TypeChecker<'a> { fn resolve_reference(&mut self, reference: &Reference, env: &mut SymbolEnv) -> (VariableInfo, Phase) { match reference { Reference::Identifier(symbol) => { - let lookup_res = env.lookup_ext_mut(symbol, Some(self.statement_idx)); + let lookup_res = env.lookup_ext_mut(symbol, Some(self.ctx.current_stmt_idx())); if let LookupResultMut::Found(var, _) = lookup_res { if let Some(var) = var.as_variable_mut() { let phase = var.phase; @@ -4496,7 +4591,7 @@ impl<'a> TypeChecker<'a> { let mut force_reassignable = false; if let ExprKind::Reference(Reference::Identifier(symb)) = &object.kind { if symb.name == "this" { - if let LookupResult::Found(kind, info) = env.lookup_ext(&symb, Some(self.statement_idx)) { + if let LookupResult::Found(kind, info) = env.lookup_ext(&symb, Some(self.ctx.current_stmt_idx())) { // `this` reserved symbol should always be a variable assert!(matches!(kind, SymbolKind::Variable(_))); force_reassignable = info.init; @@ -4546,7 +4641,7 @@ impl<'a> TypeChecker<'a> { } Reference::TypeMember { type_name, property } => { let type_ = self - .resolve_user_defined_type(type_name, env, self.statement_idx) + .resolve_user_defined_type(type_name, env, self.ctx.current_stmt_idx()) .unwrap_or_else(|e| self.type_error(e)); match *type_ { Type::Enum(ref e) => { @@ -4792,7 +4887,7 @@ impl<'a> TypeChecker<'a> { }; let parent_type = self - .resolve_user_defined_type(parent, env, self.statement_idx) + .resolve_user_defined_type(parent, env, self.ctx.current_stmt_idx()) .unwrap_or_else(|e| { self.type_error(e); self.types.error() @@ -4831,6 +4926,12 @@ impl<'a> TypeChecker<'a> { } } +impl VisitorWithContext for TypeChecker<'_> { + fn ctx(&mut self) -> &mut VisitContext { + &mut self.ctx + } +} + fn add_parent_members_to_struct_env( extends_types: &Vec, name: &Symbol, @@ -5117,7 +5218,7 @@ fn check_is_bringable(scope: &Scope) -> bool { StmtKind::Let { .. } => false, StmtKind::ForLoop { .. } => false, StmtKind::While { .. } => false, - StmtKind::IfLet { .. } => false, + StmtKind::IfLet(IfLet { .. }) => false, StmtKind::If { .. } => false, StmtKind::Break => false, StmtKind::Continue => false, diff --git a/libs/wingc/src/visit.rs b/libs/wingc/src/visit.rs index d10447d5a65..ea0835b7e34 100644 --- a/libs/wingc/src/visit.rs +++ b/libs/wingc/src/visit.rs @@ -1,8 +1,8 @@ use crate::{ ast::{ ArgList, BringSource, CalleeKind, Class, Expr, ExprKind, FunctionBody, FunctionDefinition, FunctionParameter, - FunctionSignature, Interface, InterpolatedStringPart, Literal, NewExpr, Reference, Scope, Stmt, StmtKind, Symbol, - TypeAnnotation, TypeAnnotationKind, UserDefinedType, + FunctionSignature, IfLet, Interface, InterpolatedStringPart, Literal, NewExpr, Reference, Scope, Stmt, StmtKind, + Symbol, TypeAnnotation, TypeAnnotationKind, UserDefinedType, }, dbg_panic, }; @@ -131,14 +131,14 @@ where v.visit_scope(statements); } StmtKind::Break | StmtKind::Continue => {} - StmtKind::IfLet { + StmtKind::IfLet(IfLet { value, statements, reassignable: _, var_name, elif_statements, else_statements, - } => { + }) => { v.visit_symbol(var_name); v.visit_expr(value); v.visit_scope(statements); diff --git a/libs/wingc/src/visit_context.rs b/libs/wingc/src/visit_context.rs index 2ea815724b5..fc5938f635b 100644 --- a/libs/wingc/src/visit_context.rs +++ b/libs/wingc/src/visit_context.rs @@ -179,9 +179,15 @@ impl VisitContext { pub trait VisitorWithContext { fn ctx(&mut self) -> &mut VisitContext; - fn with_expr(&mut self, expr: usize, f: impl FnOnce(&mut Self)) { + fn with_expr(&mut self, expr: ExprId, f: impl FnOnce(&mut Self)) { self.ctx().push_expr(expr); f(self); self.ctx().pop_expr(); } + + fn with_stmt(&mut self, stmt: usize, f: impl FnOnce(&mut Self)) { + self.ctx().push_stmt(stmt); + f(self); + self.ctx().pop_stmt(); + } } From a2c227288ae9d688353eeada4b156b808c274a76 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 3 Sep 2023 16:38:03 +0300 Subject: [PATCH 02/56] wip --- libs/wingc/src/ast.rs | 2 +- libs/wingc/src/type_check.rs | 75 ++++++++++++++++++++-- libs/wingc/src/type_check/jsii_importer.rs | 20 +++++- 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/libs/wingc/src/ast.rs b/libs/wingc/src/ast.rs index fc92704aa73..51454e29dee 100644 --- a/libs/wingc/src/ast.rs +++ b/libs/wingc/src/ast.rs @@ -513,7 +513,7 @@ pub struct ClassField { pub access_modifier: AccessModifier, } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum AccessModifier { Private, Public, diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index b4270663a52..8bff3e309c6 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -5,7 +5,8 @@ pub mod lifts; pub mod symbol_env; use crate::ast::{ - self, BringSource, CalleeKind, ClassField, ExprId, FunctionDefinition, IfLet, NewExpr, TypeAnnotationKind, + self, AccessModifier, BringSource, CalleeKind, ClassField, ExprId, FunctionDefinition, IfLet, NewExpr, + TypeAnnotationKind, }; use crate::ast::{ ArgList, BinaryOperator, Class as AstClass, Expr, ExprKind, FunctionBody, FunctionParameter as AstFunctionParameter, @@ -111,6 +112,8 @@ pub struct VariableInfo { pub phase: Phase, /// The kind of variable pub kind: VariableKind, + /// Access rules for this variable (only applies to methods and fields) + pub access_modifier: AccessModifier, pub docs: Option, } @@ -122,6 +125,7 @@ impl SymbolKind { reassignable: bool, is_static: bool, phase: Phase, + access_modifier: AccessModifier, docs: Option, ) -> Self { SymbolKind::Variable(VariableInfo { @@ -134,6 +138,7 @@ impl SymbolKind { } else { VariableKind::InstanceMember }, + access_modifier, docs, }) } @@ -145,6 +150,7 @@ impl SymbolKind { reassignable, phase, kind: VariableKind::Free, + access_modifier: AccessModifier::Public, docs: None, }) } @@ -1719,6 +1725,7 @@ impl<'a> TypeChecker<'a> { reassignable: false, phase: Phase::Independent, kind: VariableKind::Error, + access_modifier: AccessModifier::Public, docs: None, } } @@ -3133,7 +3140,15 @@ impl<'a> TypeChecker<'a> { } match struct_env.define( &field.name, - SymbolKind::make_member_variable(field.name.clone(), field_type, false, false, Phase::Independent, None), + SymbolKind::make_member_variable( + field.name.clone(), + field_type, + false, + false, + Phase::Independent, + AccessModifier::Public, + None, + ), StatementIdx::Top, ) { Err(type_error) => { @@ -3238,7 +3253,15 @@ impl<'a> TypeChecker<'a> { match interface_env.define( method_name, - SymbolKind::make_member_variable(method_name.clone(), method_type, false, false, sig.phase, None), + SymbolKind::make_member_variable( + method_name.clone(), + method_type, + false, + false, + sig.phase, + AccessModifier::Public, + None, + ), StatementIdx::Top, ) { Err(type_error) => { @@ -3258,6 +3281,10 @@ impl<'a> TypeChecker<'a> { } fn type_check_class(&mut self, env: &mut SymbolEnv, stmt: &Stmt, ast_class: &AstClass) { + self + .ctx + .push_class(UserDefinedType::for_class(ast_class), &env.phase, None); + // preflight classes cannot be declared inside an inflight scope // (the other way is okay) if env.phase == Phase::Inflight && ast_class.phase == Phase::Preflight { @@ -3325,6 +3352,7 @@ impl<'a> TypeChecker<'a> { field.reassignable, field.is_static, field.phase, + field.access_modifier, None, ), StatementIdx::Top, @@ -3342,6 +3370,7 @@ impl<'a> TypeChecker<'a> { &method_def.signature, env, if method_def.is_static { None } else { Some(class_type) }, + method_def.access_modifier, &mut class_env, method_name, ); @@ -3353,7 +3382,14 @@ impl<'a> TypeChecker<'a> { span: ast_class.initializer.span.clone(), }; - self.add_method_to_class_env(&ast_class.initializer.signature, env, None, &mut class_env, &init_symb); + self.add_method_to_class_env( + &ast_class.initializer.signature, + env, + None, + ast_class.initializer.access_modifier, + &mut class_env, + &init_symb, + ); let inflight_init_symb = Symbol { name: CLASS_INFLIGHT_INIT_NAME.into(), @@ -3365,6 +3401,7 @@ impl<'a> TypeChecker<'a> { &ast_class.inflight_initializer.signature, env, Some(class_type), + ast_class.inflight_initializer.access_modifier, &mut class_env, &inflight_init_symb, ); @@ -3474,6 +3511,7 @@ impl<'a> TypeChecker<'a> { } } } + self.ctx.pop_class(); } fn type_check_return(&mut self, env: &mut SymbolEnv, stmt: &Stmt, exp: &Option) { @@ -4052,6 +4090,7 @@ impl<'a> TypeChecker<'a> { method_sig: &ast::FunctionSignature, env: &mut SymbolEnv, instance_type: Option, + access_modifier: AccessModifier, class_env: &mut SymbolEnv, method_name: &Symbol, ) { @@ -4070,6 +4109,7 @@ impl<'a> TypeChecker<'a> { false, instance_type.is_none(), method_sig.phase, + access_modifier, None, ), StatementIdx::Top, @@ -4281,6 +4321,7 @@ impl<'a> TypeChecker<'a> { reassignable, phase: flight, kind, + access_modifier, docs: _, }) => { // Replace type params in function signatures @@ -4322,6 +4363,7 @@ impl<'a> TypeChecker<'a> { *reassignable, matches!(kind, VariableKind::StaticMember), *flight, + *access_modifier, None, ), StatementIdx::Top, @@ -4343,6 +4385,7 @@ impl<'a> TypeChecker<'a> { *reassignable, matches!(kind, VariableKind::StaticMember), *flight, + *access_modifier, None, ), StatementIdx::Top, @@ -4608,6 +4651,8 @@ impl<'a> TypeChecker<'a> { let mut property_variable = self.resolve_variable_from_instance_type(instance_type, property, env, object); + // TODO: Here we can get the access_modifier of the property and check it based on the current class + // if the object is `this`, then use the property's phase instead of the object phase let property_phase = if property_variable.phase == Phase::Independent { instance_phase @@ -4653,6 +4698,7 @@ impl<'a> TypeChecker<'a> { type_, reassignable: false, phase: Phase::Independent, + access_modifier: AccessModifier::Public, docs: None, }, Phase::Independent, @@ -4731,6 +4777,7 @@ impl<'a> TypeChecker<'a> { reassignable: false, phase: env.phase, kind: VariableKind::InstanceMember, + access_modifier: AccessModifier::Public, docs: None, }, @@ -4977,7 +5024,15 @@ fn add_parent_members_to_struct_env( }; struct_env.define( &sym, - SymbolKind::make_member_variable(sym.clone(), member_type, false, false, struct_env.phase, None), + SymbolKind::make_member_variable( + sym.clone(), + member_type, + false, + false, + struct_env.phase, + AccessModifier::Public, + None, + ), StatementIdx::Top, )?; } @@ -5032,7 +5087,15 @@ fn add_parent_members_to_iface_env( }; iface_env.define( &sym, - SymbolKind::make_member_variable(sym.clone(), member_type, false, true, iface_env.phase, None), + SymbolKind::make_member_variable( + sym.clone(), + member_type, + false, + true, + iface_env.phase, + AccessModifier::Public, + None, + ), StatementIdx::Top, )?; } diff --git a/libs/wingc/src/type_check/jsii_importer.rs b/libs/wingc/src/type_check/jsii_importer.rs index bf4c801a96b..602552dde32 100644 --- a/libs/wingc/src/type_check/jsii_importer.rs +++ b/libs/wingc/src/type_check/jsii_importer.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; use crate::{ - ast::{Phase, Symbol}, + ast::{AccessModifier, Phase, Symbol}, debug, diagnostic::{WingLocation, WingSpan}, docs::Docs, @@ -495,6 +495,11 @@ impl<'a> JsiiImporter<'a> { .flatten(), })); let sym = Self::jsii_name_to_symbol(&m.name, &m.location_in_module); + let access_modifier = if matches!(m.protected, Some(true)) { + AccessModifier::Protected + } else { + AccessModifier::Public + }; class_env .define( &sym, @@ -504,6 +509,7 @@ impl<'a> JsiiImporter<'a> { false, is_static, member_phase, + access_modifier, Some(Docs::from(&m.docs)), ), StatementIdx::Top, @@ -533,6 +539,11 @@ impl<'a> JsiiImporter<'a> { }; let sym = Self::jsii_name_to_symbol(&p.name, &p.location_in_module); + let access_modifier = if matches!(p.protected, Some(true)) { + AccessModifier::Protected + } else { + AccessModifier::Public + }; class_env .define( &sym, @@ -542,6 +553,7 @@ impl<'a> JsiiImporter<'a> { !matches!(p.immutable, Some(true)), is_static, member_phase, + access_modifier, Some(Docs::from(&p.docs)), ), StatementIdx::Top, @@ -751,6 +763,11 @@ impl<'a> JsiiImporter<'a> { docs: Docs::from(&initializer.docs), })); let sym = Self::jsii_name_to_symbol(CLASS_INIT_NAME, &initializer.location_in_module); + let access_modifier = if matches!(initializer.protected, Some(true)) { + AccessModifier::Protected + } else { + AccessModifier::Public + }; if let Err(e) = class_env.define( &sym, SymbolKind::make_member_variable( @@ -759,6 +776,7 @@ impl<'a> JsiiImporter<'a> { false, true, member_phase, + access_modifier, Some(Docs::from(&initializer.docs)), ), StatementIdx::Top, From c6175409f319b00b826e98423e7ea92211063fbf Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Tue, 5 Sep 2023 09:27:00 +0300 Subject: [PATCH 03/56] wip: access modifiers --- libs/wingc/src/type_check.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 8bff3e309c6..d0db000ae12 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -4652,6 +4652,34 @@ impl<'a> TypeChecker<'a> { let mut property_variable = self.resolve_variable_from_instance_type(instance_type, property, env, object); // TODO: Here we can get the access_modifier of the property and check it based on the current class + let mut private_access = false; + let mut protected_access = false; + if let Some(current_class) = self.ctx.current_class().map(|udt| udt.clone()) { + let current_class_type = self + .resolve_user_defined_type(¤t_class, env, self.ctx.current_stmt_idx()) + .unwrap(); + private_access = current_class_type.is_same_type_as(&instance_type); + protected_access = private_access || current_class_type.is_strict_subtype_of(&instance_type); + } + match property_variable.access_modifier { + AccessModifier::Private => { + if !private_access { + self.spanned_error( + property, + format!("Cannot access private member {property} of {instance_type}"), + ); + } + } + AccessModifier::Protected => { + if !protected_access { + self.spanned_error( + property, + format!("Cannot access protected member {property} of {instance_type}"), + ); + } + } + AccessModifier::Public => {} // keep this here to make sure we don't add a new access modifier without handling it here + } // if the object is `this`, then use the property's phase instead of the object phase let property_phase = if property_variable.phase == Phase::Independent { From 9437676574f41cbc305959405dacc01be76ad0f7 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Tue, 5 Sep 2023 11:41:02 +0300 Subject: [PATCH 04/56] wip --- libs/wingc/src/type_check.rs | 30 ++++++++++++++++-------------- libs/wingc/src/visit_context.rs | 1 + 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index d0db000ae12..d54c8bc00f9 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -1601,7 +1601,7 @@ pub struct TypeChecker<'a> { /// makes it a lot simpler. Ideally we should avoid returning anything here and have some way /// to iterate over the inner scopes given the outer scope. For this we need to model our AST /// so all nodes implement some basic "tree" interface. For now this is good enough. - inner_scopes: Vec<*const Scope>, + inner_scopes: Vec<(*const Scope, VisitContext)>, /// The path to the source file being type checked. source_path: &'a Utf8Path, @@ -2520,7 +2520,7 @@ impl<'a> TypeChecker<'a> { if let FunctionBody::Statements(scope) = &func_def.body { self.types.set_scope_env(scope, function_env); - self.inner_scopes.push(scope); + self.inner_scopes.push((scope, self.ctx.clone())); (function_type, sig.phase) } else { @@ -2799,8 +2799,9 @@ impl<'a> TypeChecker<'a> { // reverse list to type check later scopes first // Why? To improve the inference algorithm. Earlier inner_scopes for closures may need to infer types from later inner_scopes let inner_scopes = self.inner_scopes.drain(..).rev().collect::>(); - for inner_scope in inner_scopes { + for (inner_scope, ctx) in inner_scopes { let scope = unsafe { &*inner_scope }; + self.ctx = ctx; self.type_check_scope(scope); } if env.is_function { @@ -3002,7 +3003,7 @@ impl<'a> TypeChecker<'a> { stmt.idx, )); tc.types.set_scope_env(scope, scope_env); - tc.inner_scopes.push(scope) + tc.inner_scopes.push((scope, tc.ctx.clone())); } StmtKind::Throw(exp) => { tc.type_check_throw(exp, env); @@ -3057,7 +3058,7 @@ impl<'a> TypeChecker<'a> { stmt.idx, )); self.types.set_scope_env(try_statements, try_env); - self.inner_scopes.push(try_statements); + self.inner_scopes.push((try_statements, self.ctx.clone())); // Create a new environment for the catch block if let Some(catch_block) = catch_block { @@ -3084,7 +3085,7 @@ impl<'a> TypeChecker<'a> { } } self.types.set_scope_env(&catch_block.statements, catch_env); - self.inner_scopes.push(&catch_block.statements); + self.inner_scopes.push((&catch_block.statements, self.ctx.clone())); } // Create a new environment for the finally block @@ -3098,7 +3099,7 @@ impl<'a> TypeChecker<'a> { stmt.idx, )); self.types.set_scope_env(finally_statements, finally_env); - self.inner_scopes.push(finally_statements); + self.inner_scopes.push((finally_statements, self.ctx.clone())); } } @@ -3666,7 +3667,7 @@ impl<'a> TypeChecker<'a> { stmt.idx, )); self.types.set_scope_env(else_scope, else_scope_env); - self.inner_scopes.push(else_scope); + self.inner_scopes.push((else_scope, self.ctx.clone())); } } @@ -3701,7 +3702,7 @@ impl<'a> TypeChecker<'a> { stmt.idx, )); self.types.set_scope_env(else_scope, else_scope_env); - self.inner_scopes.push(else_scope); + self.inner_scopes.push((else_scope, self.ctx.clone())); } } @@ -3719,7 +3720,7 @@ impl<'a> TypeChecker<'a> { )); self.types.set_scope_env(statements, scope_env); - self.inner_scopes.push(statements); + self.inner_scopes.push((statements, self.ctx.clone())); } fn type_check_for_loop( @@ -3767,7 +3768,7 @@ impl<'a> TypeChecker<'a> { }; self.types.set_scope_env(statements, scope_env); - self.inner_scopes.push(statements); + self.inner_scopes.push((statements, self.ctx.clone())); } fn type_check_let( @@ -3887,7 +3888,7 @@ impl<'a> TypeChecker<'a> { } self.types.set_scope_env(statements, stmt_env); - self.inner_scopes.push(statements); + self.inner_scopes.push((statements, self.ctx.clone())); } fn type_check_if_statement(&mut self, condition: &Expr, statements: &Scope, stmt: &Stmt, env: &mut SymbolEnv) { @@ -3903,7 +3904,7 @@ impl<'a> TypeChecker<'a> { stmt.idx, )); self.types.set_scope_env(statements, if_scope_env); - self.inner_scopes.push(statements); + self.inner_scopes.push((statements, self.ctx.clone())); } fn type_check_super_constructor_against_parent_initializer( @@ -4072,7 +4073,7 @@ impl<'a> TypeChecker<'a> { if let FunctionBody::Statements(scope) = &method_def.body { self.types.set_scope_env(scope, method_env); - self.inner_scopes.push(scope); + self.inner_scopes.push((scope, self.ctx.clone())); } if let FunctionBody::External(_) = &method_def.body { @@ -4658,6 +4659,7 @@ impl<'a> TypeChecker<'a> { let current_class_type = self .resolve_user_defined_type(¤t_class, env, self.ctx.current_stmt_idx()) .unwrap(); + // TODO: instance type is wrong here we type where property is defined (might be a super class) private_access = current_class_type.is_same_type_as(&instance_type); protected_access = private_access || current_class_type.is_strict_subtype_of(&instance_type); } diff --git a/libs/wingc/src/visit_context.rs b/libs/wingc/src/visit_context.rs index fc5938f635b..6ef1ea3160e 100644 --- a/libs/wingc/src/visit_context.rs +++ b/libs/wingc/src/visit_context.rs @@ -3,6 +3,7 @@ use crate::{ type_check::symbol_env::SymbolEnvRef, }; +#[derive(Clone)] pub struct VisitContext { phase: Vec, env: Vec, From a8d46271d91bc52330899ef35a29905595b4aee9 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 7 Sep 2023 08:21:39 +0300 Subject: [PATCH 05/56] wip --- libs/wingc/src/lib.rs | 4 +- libs/wingc/src/lifting.rs | 8 +- libs/wingc/src/type_check.rs | 270 ++++++++++----------- libs/wingc/src/type_check/jsii_importer.rs | 50 ++-- libs/wingc/src/type_check/symbol_env.rs | 73 +++--- libs/wingc/src/visit_context.rs | 76 ++++-- 6 files changed, 248 insertions(+), 233 deletions(-) diff --git a/libs/wingc/src/lib.rs b/libs/wingc/src/lib.rs index 1d9075316eb..3a886e19277 100644 --- a/libs/wingc/src/lib.rs +++ b/libs/wingc/src/lib.rs @@ -20,7 +20,7 @@ use jsify::JSifier; use lifting::LiftVisitor; use parser::parse_wing_project; use type_check::jsii_importer::JsiiImportSpec; -use type_check::symbol_env::StatementIdx; +use type_check::symbol_env::{StatementIdx, SymbolEnvKind}; use type_check::{FunctionSignature, SymbolKind, Type}; use type_check_assert::TypeCheckAssert; use valid_json_visitor::ValidJsonVisitor; @@ -198,7 +198,7 @@ pub fn type_check( jsii_types: &mut TypeSystem, jsii_imports: &mut Vec, ) { - let env = types.add_symbol_env(SymbolEnv::new(None, types.void(), false, false, Phase::Preflight, 0)); + let env = types.add_symbol_env(SymbolEnv::new(None, SymbolEnvKind::Scope, Phase::Preflight, 0)); types.set_scope_env(scope, env); // note: Globals are emitted here and wrapped in "{ ... }" blocks. Wrapping makes these emissions, actual diff --git a/libs/wingc/src/lifting.rs b/libs/wingc/src/lifting.rs index 5e131ab4bc3..72a884ed872 100644 --- a/libs/wingc/src/lifting.rs +++ b/libs/wingc/src/lifting.rs @@ -215,7 +215,7 @@ impl<'a> Visit<'a> for LiftVisitor<'a> { let mut lifts = v.lifts_stack.pop().unwrap(); let is_field = code.contains("this."); // TODO: starts_with? - lifts.lift(v.ctx.current_method(), property, &code, is_field); + lifts.lift(v.ctx.current_method().map(|(m,_)|m), property, &code, is_field); lifts.capture(&Liftable::Expr(node.id), &code, is_field); v.lifts_stack.push(lifts); return; @@ -273,7 +273,7 @@ impl<'a> Visit<'a> for LiftVisitor<'a> { } let mut lifts = self.lifts_stack.pop().unwrap(); - lifts.lift(self.ctx.current_method(), property, &code, false); + lifts.lift(self.ctx.current_method().map(|(m, _)| m), property, &code, false); self.lifts_stack.push(lifts); } @@ -299,8 +299,8 @@ impl<'a> Visit<'a> for LiftVisitor<'a> { match &node.body { FunctionBody::Statements(scope) => { self.ctx.push_function_definition( - &node.name, - &node.signature.phase, + node.name.as_ref(), + &node.signature, self.jsify.types.get_scope_env(&scope), ); diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index d54c8bc00f9..7225bfb9fd2 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -16,6 +16,7 @@ use crate::ast::{ use crate::comp_ctx::{CompilationContext, CompilationPhase}; use crate::diagnostic::{report_diagnostic, Diagnostic, TypeError, WingSpan}; use crate::docs::Docs; +use crate::type_check::symbol_env::SymbolEnvKind; use crate::visit_context::{VisitContext, VisitorWithContext}; use crate::visit_types::{VisitType, VisitTypeMut}; use crate::{ @@ -919,6 +920,14 @@ impl TypeRef { } } + pub fn as_mut_struct(&mut self) -> Option<&mut Struct> { + if let Type::Struct(ref mut st) = **self { + Some(st) + } else { + None + } + } + pub fn as_interface(&self) -> Option<&Interface> { if let Type::Interface(ref iface) = **self { Some(iface) @@ -1289,10 +1298,7 @@ impl Types { types.push(Box::new(Type::Unresolved)); let err_idx = types.len() - 1; - // TODO: this is hack to create the top-level mapping from lib names to symbols - // We construct a void ref by hand since we can't call self.void() while constructing the Types struct - let void_ref = UnsafeRef::(&*types[void_idx] as *const Type); - let libraries = SymbolEnv::new(None, void_ref, false, false, Phase::Preflight, 0); + let libraries = SymbolEnv::new(None, SymbolEnvKind::Scope, Phase::Preflight, 0); Self { types, @@ -2501,6 +2507,7 @@ impl<'a> TypeChecker<'a> { fn type_check_closure(&mut self, func_def: &ast::FunctionDefinition, env: &SymbolEnv) -> (TypeRef, Phase) { // TODO: make sure this function returns on all control paths when there's a return type (can be done by recursively traversing the statements and making sure there's a "return" statements in all control paths) // https://github.com/winglang/wing/issues/457 + // Create a type_checker function signature from the AST function definition let function_type = self.resolve_type_annotation(&func_def.signature.to_type_annotation(), env); let sig = function_type.as_function_sig().unwrap(); @@ -2508,24 +2515,24 @@ impl<'a> TypeChecker<'a> { // Create an environment for the function let mut function_env = self.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - sig.return_type, - false, - true, + SymbolEnvKind::Function { is_init: false }, func_def.signature.phase, self.ctx.current_stmt_idx(), )); self.add_arguments_to_env(&func_def.signature.parameters, &sig, &mut function_env); - // Type check the function body - if let FunctionBody::Statements(scope) = &func_def.body { - self.types.set_scope_env(scope, function_env); + self.with_function_def(None, &func_def.signature, function_env, |tc| { + // Type check the function body + if let FunctionBody::Statements(scope) = &func_def.body { + tc.types.set_scope_env(scope, function_env); - self.inner_scopes.push((scope, self.ctx.clone())); + tc.inner_scopes.push((scope, tc.ctx.clone())); - (function_type, sig.phase) - } else { - (function_type, sig.phase) - } + (function_type, sig.phase) + } else { + (function_type, sig.phase) + } + }) } /// Validate that a given map can be assigned to a variable of given struct type @@ -2804,15 +2811,15 @@ impl<'a> TypeChecker<'a> { self.ctx = ctx; self.type_check_scope(scope); } - if env.is_function { - if let Type::Inferred(n) = &*env.return_type { - if self.types.get_inference_by_id(*n).is_none() { - // If function types don't return anything then we should set the return type to void - self.types.update_inferred_type(*n, self.types.void(), &scope.span); - } - self.update_known_inferences(&mut env.return_type, &scope.span); - } - } + // if matches!(env.kind, SymbolEnvKind::Function { .. }) { + // if let Type::Inferred(n) = &*env.return_type { + // if self.types.get_inference_by_id(*n).is_none() { + // // If function types don't return anything then we should set the return type to void + // self.types.update_inferred_type(*n, self.types.void(), &scope.span); + // } + // self.update_known_inferences(&mut env.return_type, &scope.span); + // } + // } for symbol_data in env.symbol_map.values_mut() { if let SymbolKind::Variable(ref mut var_info) = symbol_data.1 { @@ -2996,9 +3003,7 @@ impl<'a> TypeChecker<'a> { StmtKind::Scope(scope) => { let scope_env = tc.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - env.return_type, - false, - false, + SymbolEnvKind::Scope, env.phase, stmt.idx, )); @@ -3051,9 +3056,7 @@ impl<'a> TypeChecker<'a> { // Create a new environment for the try block let try_env = self.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - env.return_type, - false, - false, + SymbolEnvKind::Scope, env.phase, stmt.idx, )); @@ -3064,9 +3067,7 @@ impl<'a> TypeChecker<'a> { if let Some(catch_block) = catch_block { let mut catch_env = self.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - env.return_type, - false, - false, + SymbolEnvKind::Scope, env.phase, stmt.idx, )); @@ -3092,9 +3093,7 @@ impl<'a> TypeChecker<'a> { if let Some(finally_statements) = finally_statements { let finally_env = self.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - env.return_type, - false, - false, + SymbolEnvKind::Scope, env.phase, stmt.idx, )); @@ -3130,8 +3129,40 @@ impl<'a> TypeChecker<'a> { // If we encounter an existing member with the same name and type we skip it, if the types are different we // fail type checking. - // Create an environment for the struct - let mut struct_env = SymbolEnv::new(None, self.types.void(), false, false, Phase::Independent, stmt.idx); + // Create a dummy environment for the struct so we can create the struct type + let dummy_env = SymbolEnv::new( + None, + SymbolEnvKind::Type(self.types.void()), + Phase::Independent, + stmt.idx, + ); + + // Collect types this struct extends + let extends_types = extends + .iter() + .filter_map(|ext| { + let t = self + .resolve_user_defined_type(ext, env, stmt.idx) + .unwrap_or_else(|e| self.type_error(e)); + if t.as_struct().is_some() { + Some(t) + } else { + self.spanned_error(ext, format!("Expected a struct, found type \"{}\"", t)); + None + } + }) + .collect::>(); + + // Create the struct type + let mut struct_type = self.types.add_type(Type::Struct(Struct { + name: name.clone(), + extends: extends_types.clone(), + env: dummy_env, + docs: Docs::default(), + })); + + // Create the actual environment for the struct + let mut struct_env = SymbolEnv::new(None, SymbolEnvKind::Type(struct_type), Phase::Independent, stmt.idx); // Add fields to the struct env for field in fields.iter() { @@ -3159,40 +3190,18 @@ impl<'a> TypeChecker<'a> { }; } - // Add members from the structs parents - let extends_types = extends - .iter() - .filter_map(|ext| { - let t = self - .resolve_user_defined_type(ext, env, stmt.idx) - .unwrap_or_else(|e| self.type_error(e)); - if t.as_struct().is_some() { - Some(t) - } else { - self.spanned_error(ext, format!("Expected a struct, found type \"{}\"", t)); - None - } - }) - .collect::>(); - if let Err(e) = add_parent_members_to_struct_env(&extends_types, name, &mut struct_env) { self.type_error(e); } - match env.define( - name, - SymbolKind::Type(self.types.add_type(Type::Struct(Struct { - name: name.clone(), - extends: extends_types, - env: struct_env, - docs: Docs::default(), - }))), - StatementIdx::Top, - ) { + match env.define(name, SymbolKind::Type(struct_type), StatementIdx::Top) { Err(type_error) => { self.type_error(type_error); } _ => {} }; + + // Replace the dummy struct environment with the real one + struct_type.as_mut_struct().unwrap().env = struct_env; } fn type_check_interface( @@ -3204,7 +3213,7 @@ impl<'a> TypeChecker<'a> { methods: &Vec<(Symbol, ast::FunctionSignature)>, ) { // Create environment representing this interface, for now it'll be empty just so we can support referencing ourselves from the interface definition. - let dummy_env = SymbolEnv::new(None, self.types.void(), false, false, env.phase, stmt.idx); + let dummy_env = SymbolEnv::new(None, SymbolEnvKind::Type(self.types.void()), env.phase, stmt.idx); let extend_interfaces = extends .iter() @@ -3240,7 +3249,7 @@ impl<'a> TypeChecker<'a> { }; // Create the real interface environment to be filled with the interface AST types - let mut interface_env = SymbolEnv::new(None, self.types.void(), false, false, env.phase, stmt.idx); + let mut interface_env = SymbolEnv::new(None, SymbolEnvKind::Type(interface_type), env.phase, stmt.idx); // Add methods to the interface env for (method_name, sig) in methods.iter() { @@ -3277,7 +3286,7 @@ impl<'a> TypeChecker<'a> { self.type_error(e); } - // Replace the dummy interface environment with the real one before type checking the methods + // Replace the dummy interface environment with the real one interface_type.as_mut_interface().unwrap().env = interface_env; } @@ -3299,7 +3308,7 @@ impl<'a> TypeChecker<'a> { self.extract_parent_class(ast_class.parent.as_ref(), ast_class.phase, &ast_class.name, env); // Create environment representing this class, for now it'll be empty just so we can support referencing ourselves from the class definition. - let dummy_env = SymbolEnv::new(None, self.types.void(), false, false, env.phase, stmt.idx); + let dummy_env = SymbolEnv::new(None, SymbolEnvKind::Type(self.types.void()), env.phase, stmt.idx); let impl_interfaces = ast_class .implements @@ -3340,7 +3349,7 @@ impl<'a> TypeChecker<'a> { }; // Create a the real class environment to be filled with the class AST types - let mut class_env = SymbolEnv::new(parent_class_env, self.types.void(), false, false, env.phase, stmt.idx); + let mut class_env = SymbolEnv::new(parent_class_env, SymbolEnvKind::Type(class_type), env.phase, stmt.idx); // Add fields to the class env for field in ast_class.fields.iter() { @@ -3516,28 +3525,43 @@ impl<'a> TypeChecker<'a> { } fn type_check_return(&mut self, env: &mut SymbolEnv, stmt: &Stmt, exp: &Option) { - let return_type_inferred = self.update_known_inferences(&mut env.return_type, &stmt.span); + //let return_type_inferred = self.update_known_inferences(&mut env.return_type, &stmt.span); + + // Make sure we're inside a function + let Some((_, current_func_sig)) = self.ctx.current_method() else { + self.spanned_error(stmt, "Return statement outside of function cannot return a value"); + return; + }; + + // Get the expected return type, we need to look it up in the parent of the current function's env + let function_def_env = self + .ctx + .current_function_env() + .expect("Expected to be in a function") + .parent + .expect("Function is defined in an env"); + let mut function_ret_type = self.resolve_type_annotation(¤t_func_sig.return_type, &function_def_env); + if let Some(return_expression) = exp { let (return_type, _) = self.type_check_exp(return_expression, env); - if !env.return_type.is_void() { - self.validate_type(return_type, env.return_type, return_expression); - } else if env.is_in_function() { - if return_type_inferred { - self.spanned_error(stmt, "Unexpected return value from void function"); - } else { - self.spanned_error( - stmt, - "Unexpected return value from void function. Return type annotations are required for methods.", - ); - } + + if !function_ret_type.is_void() { + self.validate_type(return_type, function_ret_type, return_expression); } else { - self.spanned_error(stmt, "Return statement outside of function cannot return a value"); + //if return_type_inferred { + self.spanned_error(stmt, "Unexpected return value from void function"); + // } else { + // self.spanned_error( + // stmt, + // "Unexpected return value from void function. Return type annotations are required for methods.", + // ); + // } } } else { - self.validate_type(self.types.void(), env.return_type, stmt); + self.validate_type(self.types.void(), function_ret_type, stmt); } - if let Type::Json(d) = &mut *env.return_type { + if let Type::Json(d) = &mut *function_ret_type { // We do not have the required analysis to know the type of the Json data after return if d.is_some() { d.take(); @@ -3597,14 +3621,7 @@ impl<'a> TypeChecker<'a> { } let ns = self.types.add_namespace(Namespace { name: name.name.to_string(), - env: SymbolEnv::new( - Some(brought_env.get_ref()), - brought_env.return_type, - false, - false, - brought_env.phase, - 0, - ), + env: SymbolEnv::new(Some(brought_env.get_ref()), SymbolEnvKind::Scope, brought_env.phase, 0), loaded: true, }); if let Err(e) = env.define( @@ -3660,9 +3677,7 @@ impl<'a> TypeChecker<'a> { if let Some(else_scope) = else_statements { let else_scope_env = self.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - env.return_type, - false, - false, + SymbolEnvKind::Scope, env.phase, stmt.idx, )); @@ -3695,9 +3710,7 @@ impl<'a> TypeChecker<'a> { if let Some(else_scope) = &iflet.else_statements { let else_scope_env = self.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - env.return_type, - false, - false, + SymbolEnvKind::Scope, env.phase, stmt.idx, )); @@ -3712,9 +3725,7 @@ impl<'a> TypeChecker<'a> { let scope_env = self.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - env.return_type, - false, - false, + SymbolEnvKind::Scope, env.phase, stmt.idx, )); @@ -3750,9 +3761,7 @@ impl<'a> TypeChecker<'a> { let mut scope_env = self.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - env.return_type, - false, - false, + SymbolEnvKind::Scope, env.phase, stmt.idx, )); @@ -3868,9 +3877,7 @@ impl<'a> TypeChecker<'a> { let mut stmt_env = self.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - env.return_type, - false, - false, + SymbolEnvKind::Scope, env.phase, stmt.idx, )); @@ -3897,9 +3904,7 @@ impl<'a> TypeChecker<'a> { let if_scope_env = self.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - env.return_type, - false, - false, + SymbolEnvKind::Scope, env.phase, stmt.idx, )); @@ -3937,9 +3942,7 @@ impl<'a> TypeChecker<'a> { // Create a temp init environment to use for typechecking args let init_env = &mut SymbolEnv::new( Some(class_env.get_ref()), - self.types.void(), - true, - true, + SymbolEnvKind::Function { is_init: true }, class_env.phase, scope.statements[0].idx, ); @@ -4050,9 +4053,7 @@ impl<'a> TypeChecker<'a> { let is_init = method_name.name == CLASS_INIT_NAME || method_name.name == CLASS_INFLIGHT_INIT_NAME; let mut method_env = self.types.add_symbol_env(SymbolEnv::new( Some(parent_env.get_ref()), - method_sig.return_type, - is_init, - true, + SymbolEnvKind::Function { is_init }, method_sig.phase, statement_idx, )); @@ -4071,19 +4072,21 @@ impl<'a> TypeChecker<'a> { } self.add_arguments_to_env(&method_def.signature.parameters, method_sig, &mut method_env); - if let FunctionBody::Statements(scope) = &method_def.body { - self.types.set_scope_env(scope, method_env); - self.inner_scopes.push((scope, self.ctx.clone())); - } + self.with_function_def(Some(method_name), &method_def.signature, method_env, |tc| { + if let FunctionBody::Statements(scope) = &method_def.body { + tc.types.set_scope_env(scope, method_env); + tc.inner_scopes.push((scope, tc.ctx.clone())); + } - if let FunctionBody::External(_) = &method_def.body { - if !method_def.is_static { - self.spanned_error( - method_name, - "Extern methods must be declared \"static\" (they cannot access instance members)", - ); + if let FunctionBody::External(_) = &method_def.body { + if !method_def.is_static { + tc.spanned_error( + method_name, + "Extern methods must be declared \"static\" (they cannot access instance members)", + ); + } } - } + }); } fn add_method_to_class_env( @@ -4286,14 +4289,7 @@ impl<'a> TypeChecker<'a> { types_map.insert(format!("{o}"), (*o, *n)); } - let new_env = SymbolEnv::new( - None, - original_type_class.env.return_type, - false, - false, - Phase::Independent, - 0, - ); + let mut new_env = SymbolEnv::new(None, SymbolEnvKind::Type(original_type), Phase::Independent, 0); let tt = Type::Class(Class { name: original_type_class.name.clone(), env: new_env, @@ -4311,6 +4307,8 @@ impl<'a> TypeChecker<'a> { // TODO: here we add a new type regardless whether we already "hydrated" `original_type` with these `type_params`. Cache! let mut new_type = self.types.add_type(tt); let new_type_class = new_type.as_class_mut().unwrap(); + // Update the type's environment with the new type + new_type_class.env.kind = SymbolEnvKind::Type(new_type); // Add symbols from original type to new type // Note: this is currently limited to top-level function signatures and fields @@ -5227,7 +5225,7 @@ pub fn resolve_super_method(method: &Symbol, env: &SymbolEnv, types: &Types) -> } } else { Err(TypeError { - message: (if env.is_function { + message: (if matches!(env.kind, SymbolEnvKind::Function { .. }) { "Cannot call super method inside of a static method" } else { "\"super\" can only be used inside of classes" diff --git a/libs/wingc/src/type_check/jsii_importer.rs b/libs/wingc/src/type_check/jsii_importer.rs index 602552dde32..2672b62a5d2 100644 --- a/libs/wingc/src/type_check/jsii_importer.rs +++ b/libs/wingc/src/type_check/jsii_importer.rs @@ -6,8 +6,9 @@ use crate::{ diagnostic::{WingLocation, WingSpan}, docs::Docs, type_check::{ - self, symbol_env::StatementIdx, Class, FunctionParameter, FunctionSignature, Interface, Struct, SymbolKind, Type, - TypeRef, Types, CLASS_INIT_NAME, + self, + symbol_env::{StatementIdx, SymbolEnvKind}, + Class, FunctionParameter, FunctionSignature, Interface, Struct, SymbolKind, Type, TypeRef, Types, CLASS_INIT_NAME, }, CONSTRUCT_BASE_CLASS, WINGSDK_ASSEMBLY_NAME, WINGSDK_DURATION, WINGSDK_JSON, WINGSDK_MUT_JSON, WINGSDK_RESOURCE, }; @@ -202,7 +203,7 @@ impl<'a> JsiiImporter<'a> { } else { let ns = self.wing_types.add_namespace(Namespace { name: type_name.assembly().to_string(), - env: SymbolEnv::new(None, self.wing_types.void(), false, false, Phase::Preflight, 0), + env: SymbolEnv::new(None, SymbolEnvKind::Scope, Phase::Preflight, 0), loaded: false, }); self @@ -244,7 +245,7 @@ impl<'a> JsiiImporter<'a> { } else { let ns = self.wing_types.add_namespace(Namespace { name: namespace_name.to_string(), - env: SymbolEnv::new(None, self.wing_types.void(), false, false, Phase::Preflight, 0), + env: SymbolEnv::new(None, SymbolEnvKind::Scope, Phase::Preflight, 0), loaded: false, }); parent_ns @@ -301,18 +302,12 @@ impl<'a> JsiiImporter<'a> { _ => false, }; - let mut iface_env = SymbolEnv::new( - None, - self.wing_types.void(), - false, - false, - if is_struct { - Phase::Independent - } else { - Phase::Preflight - }, - self.jsii_spec.import_statement_idx, - ); + let phase = if is_struct { + Phase::Independent + } else { + Phase::Preflight + }; + let new_type_symbol = Self::jsii_name_to_symbol(&type_name, &jsii_interface.location_in_module); let mut wing_type = match is_struct { true => self.wing_types.add_type(Type::Struct(Struct { @@ -323,9 +318,7 @@ impl<'a> JsiiImporter<'a> { // Will be replaced below env: SymbolEnv::new( None, - self.wing_types.void(), - false, - false, + SymbolEnvKind::Type(self.wing_types.void()), Phase::Independent, // structs are phase-independent self.jsii_spec.import_statement_idx, ), @@ -338,10 +331,8 @@ impl<'a> JsiiImporter<'a> { // Will be replaced below env: SymbolEnv::new( None, - self.wing_types.void(), - false, - false, - iface_env.phase, + SymbolEnvKind::Type(self.wing_types.void()), + phase, self.jsii_spec.import_statement_idx, ), })), @@ -360,6 +351,13 @@ impl<'a> JsiiImporter<'a> { } }; + let mut iface_env = SymbolEnv::new( + None, + SymbolEnvKind::Type(wing_type), + phase, + self.jsii_spec.import_statement_idx, + ); + self.add_members_to_class_env( jsii_interface, Phase::Inflight, @@ -655,7 +653,7 @@ impl<'a> JsiiImporter<'a> { }; // Create environment representing this class, for now it'll be empty just so we can support referencing ourselves from the class definition. - let dummy_env = SymbolEnv::new(None, self.wing_types.void(), false, false, class_phase, 0); + let dummy_env = SymbolEnv::new(None, SymbolEnvKind::Type(self.wing_types.void()), class_phase, 0); let new_type_symbol = Self::jsii_name_to_symbol(type_name, &jsii_class.location_in_module); // Create the new resource/class type and add it to the current environment. // When adding the class methods below we'll be able to reference this type. @@ -709,7 +707,7 @@ impl<'a> JsiiImporter<'a> { }; // Create class's actual environment before we add properties and methods to it - let mut class_env = SymbolEnv::new(base_class_env, self.wing_types.void(), false, false, class_phase, 0); + let mut class_env = SymbolEnv::new(base_class_env, SymbolEnvKind::Type(new_type), class_phase, 0); // Add constructor to the class environment let jsii_initializer = jsii_class.initializer.as_ref(); @@ -952,7 +950,7 @@ impl<'a> JsiiImporter<'a> { { let ns = self.wing_types.add_namespace(Namespace { name: assembly.name.clone(), - env: SymbolEnv::new(None, self.wing_types.void(), false, false, Phase::Preflight, 0), + env: SymbolEnv::new(None, SymbolEnvKind::Scope, Phase::Preflight, 0), loaded: false, }); self diff --git a/libs/wingc/src/type_check/symbol_env.rs b/libs/wingc/src/type_check/symbol_env.rs index ccdeb9aeb45..e23cd61ceac 100644 --- a/libs/wingc/src/type_check/symbol_env.rs +++ b/libs/wingc/src/type_check/symbol_env.rs @@ -22,17 +22,18 @@ pub struct SymbolEnv { pub(crate) symbol_map: BTreeMap, pub(crate) parent: Option, - // TODO: This doesn't make much sense in the context of the "environment" but I needed a way to propagate the return type of a function - // down the scopes. Think of a nicer way to do this. - pub return_type: TypeRef, + pub kind: SymbolEnvKind, - pub is_init: bool, - // Whether this scope is inside of a function - pub is_function: bool, pub phase: Phase, statement_idx: usize, } +pub enum SymbolEnvKind { + Scope, + Function { is_init: bool }, + Type(TypeRef), +} + impl Display for SymbolEnv { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut level = 0; @@ -153,23 +154,19 @@ pub struct SymbolLookupInfo { } impl SymbolEnv { - pub fn new( - parent: Option, - return_type: TypeRef, - is_init: bool, - is_function: bool, - phase: Phase, - statement_idx: usize, - ) -> Self { - // assert that if the return type isn't void, then there is a parent environment - assert!(matches!(*return_type, Type::Void) || parent.is_some()); + pub fn new(parent: Option, kind: SymbolEnvKind, phase: Phase, statement_idx: usize) -> Self { + // Some sanity checks + // If parent is a type-environent this must be one too, otherwise it must not be + assert!( + matches!(parent, Some(parent) if matches!(parent.kind, SymbolEnvKind::Type(_)) == matches!(kind, SymbolEnvKind::Type(_))) + ); + // + //assert!(matches!(*return_type, Type::Void) || parent.is_some()); Self { symbol_map: BTreeMap::new(), parent, - return_type, - is_init, - is_function, + kind, phase, statement_idx, } @@ -270,7 +267,7 @@ impl SymbolEnv { kind, SymbolLookupInfo { phase: self.phase, - init: self.is_init, + init: matches!(self.kind, SymbolEnvKind::Function { is_init: true }), env: get_ref, }, ); @@ -356,11 +353,7 @@ impl SymbolEnv { } pub fn is_in_function(&self) -> bool { - let mut curr_env = self.get_ref(); - while !curr_env.is_function && !curr_env.is_root() { - curr_env = curr_env.parent.unwrap(); - } - curr_env.is_function + matches!(self.kind, SymbolEnvKind::Function { .. }) } } @@ -396,7 +389,7 @@ impl<'a> Iterator for SymbolEnvIter<'a> { kind, SymbolLookupInfo { phase: self.curr_env.phase, - init: self.curr_env.is_init, + init: matches!(self.curr_env.kind, SymbolEnvKind::Function { is_init: true }), env: self.curr_env.get_ref(), }, )) @@ -419,7 +412,10 @@ impl<'a> Iterator for SymbolEnvIter<'a> { mod tests { use crate::{ ast::{Phase, Symbol}, - type_check::{symbol_env::LookupResult, Namespace, SymbolKind, Types}, + type_check::{ + symbol_env::{LookupResult, SymbolEnvKind}, + Namespace, SymbolKind, Types, + }, }; use super::{StatementIdx, SymbolEnv}; @@ -431,13 +427,11 @@ mod tests { #[test] fn test_statement_idx_lookups() { let types = setup_types(); - let mut parent_env = SymbolEnv::new(None, types.void(), false, false, Phase::Independent, 0); + let mut parent_env = SymbolEnv::new(None, SymbolEnvKind::Scope, Phase::Independent, 0); let child_scope_idx = 10; let mut child_env = SymbolEnv::new( Some(parent_env.get_ref()), - types.void(), - false, - false, + SymbolEnvKind::Scope, crate::ast::Phase::Independent, child_scope_idx, ); @@ -551,12 +545,10 @@ mod tests { #[test] fn test_nested_lookups() { let mut types = setup_types(); - let mut parent_env = SymbolEnv::new(None, types.void(), false, false, Phase::Independent, 0); + let mut parent_env = SymbolEnv::new(None, SymbolEnvKind::Scope, Phase::Independent, 0); let child_env = SymbolEnv::new( Some(parent_env.get_ref()), - types.void(), - false, - false, + SymbolEnvKind::Scope, crate::ast::Phase::Independent, 0, ); @@ -564,19 +556,12 @@ mod tests { // Create namespaces let ns1 = types.add_namespace(Namespace { name: "ns1".to_string(), - env: SymbolEnv::new(None, types.void(), false, false, Phase::Independent, 0), + env: SymbolEnv::new(None, SymbolEnvKind::Scope, Phase::Independent, 0), loaded: false, }); let ns2 = types.add_namespace(Namespace { name: "ns2".to_string(), - env: SymbolEnv::new( - Some(ns1.env.get_ref()), - types.void(), - false, - false, - Phase::Independent, - 0, - ), + env: SymbolEnv::new(Some(ns1.env.get_ref()), SymbolEnvKind::Scope, Phase::Independent, 0), loaded: false, }); diff --git a/libs/wingc/src/visit_context.rs b/libs/wingc/src/visit_context.rs index 6ef1ea3160e..5284a68cf94 100644 --- a/libs/wingc/src/visit_context.rs +++ b/libs/wingc/src/visit_context.rs @@ -1,5 +1,5 @@ use crate::{ - ast::{ExprId, Phase, Symbol, UserDefinedType}, + ast::{ExprId, FunctionSignature, Phase, Symbol, UserDefinedType}, type_check::symbol_env::SymbolEnvRef, }; @@ -7,9 +7,9 @@ use crate::{ pub struct VisitContext { phase: Vec, env: Vec, - method_env: Vec>, + function_env: Vec, property: Vec, - method: Vec>, + function: Vec<(Option, FunctionSignature)>, class: Vec, statement: Vec, in_json: Vec, @@ -22,11 +22,11 @@ impl VisitContext { VisitContext { phase: vec![], env: vec![], - method_env: vec![], + function_env: vec![], property: vec![], class: vec![], statement: vec![], - method: vec![], + function: vec![], in_json: vec![], in_type_annotation: vec![], expression: vec![], @@ -77,16 +77,14 @@ impl VisitContext { // -- - pub fn push_class(&mut self, class: UserDefinedType, phase: &Phase, initializer_env: Option) { + pub fn push_class(&mut self, class: UserDefinedType, phase: &Phase) { self.class.push(class); self.push_phase(*phase); - self.method_env.push(initializer_env); } pub fn pop_class(&mut self) { self.class.pop(); self.pop_phase(); - self.method_env.pop(); } pub fn current_class(&self) -> Option<&UserDefinedType> { @@ -95,25 +93,35 @@ impl VisitContext { // -- - pub fn push_function_definition(&mut self, function_name: &Option, phase: &Phase, env: SymbolEnvRef) { - self.push_phase(*phase); - self.method.push(function_name.clone()); - - // if the function definition doesn't have a name (i.e. it's a closure), don't push its env - // because it's not a method dude! - let maybe_env = function_name.as_ref().map(|_| env); - self.method_env.push(maybe_env); + pub fn push_function_definition( + &mut self, + function_name: Option<&Symbol>, + sig: &FunctionSignature, + env: SymbolEnvRef, + ) { + self.push_phase(sig.phase); + self.function.push((function_name.cloned(), sig.clone())); + self.function_env.push(env); } pub fn pop_function_definition(&mut self) { self.pop_phase(); - self.method.pop(); - self.method_env.pop(); + self.function.pop(); + self.function_env.pop(); } - pub fn current_method(&self) -> Option { + pub fn current_method(&self) -> Option<(Symbol, FunctionSignature)> { // return the first none-None method in the stack (from the end) - self.method.iter().rev().find_map(|m| m.clone()) + self + .function + .iter() + .rev() + .find(|(m, _)| m.is_some()) + .map(|(m, sig)| (m.clone().unwrap(), sig.clone())) + } + + pub fn current_function(&self) -> Option<(Option, FunctionSignature)> { + self.function.last().cloned() } pub fn current_phase(&self) -> Phase { @@ -121,7 +129,20 @@ impl VisitContext { } pub fn current_method_env(&self) -> Option<&SymbolEnvRef> { - self.method_env.iter().rev().find_map(|m| m.as_ref()) + // Get the env of the first named function in the stack (non named functions are closures) + self.function.iter().zip(self.function_env.iter()).rev().find_map( + |((m, _), e)| { + if m.is_some() { + Some(e) + } else { + None + } + }, + ) + } + + pub fn current_function_env(&self) -> Option<&SymbolEnvRef> { + self.function_env.last() } // -- @@ -191,4 +212,17 @@ pub trait VisitorWithContext { f(self); self.ctx().pop_stmt(); } + + fn with_function_def( + &mut self, + function_name: Option<&Symbol>, + sig: &FunctionSignature, + env: SymbolEnvRef, + f: impl FnOnce(&mut Self) -> T, + ) -> T { + self.ctx().push_function_definition(function_name, sig, env); + let res = f(self); + self.ctx().pop_function_definition(); + res + } } From e3fb276f7a0987638d6088bca705cf58d706e98b Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 7 Sep 2023 11:46:59 +0300 Subject: [PATCH 06/56] wip --- libs/wingc/src/lifting.rs | 12 ++++++------ libs/wingc/src/type_check.rs | 15 ++++++++------- libs/wingc/src/type_check/symbol_env.rs | 7 +++---- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/libs/wingc/src/lifting.rs b/libs/wingc/src/lifting.rs index 72a884ed872..c2357b25b1d 100644 --- a/libs/wingc/src/lifting.rs +++ b/libs/wingc/src/lifting.rs @@ -339,11 +339,11 @@ impl<'a> Visit<'a> for LiftVisitor<'a> { // extract the "env" from the class initializer and push it to the context // because this is the environment in which we want to resolve references // as oppose to the environment of the class definition itself. - let init_env = if let FunctionBody::Statements(ref s) = node.initializer.body { - Some(self.jsify.types.get_scope_env(&s)) - } else { - None - }; + // let init_env = if let FunctionBody::Statements(ref s) = node.initializer.body { + // Some(self.jsify.types.get_scope_env(&s)) + // } else { + // None + // }; let udt = UserDefinedType { root: node.name.clone(), @@ -351,7 +351,7 @@ impl<'a> Visit<'a> for LiftVisitor<'a> { span: node.name.span.clone(), }; - self.ctx.push_class(udt.clone(), &node.phase, init_env); + self.ctx.push_class(udt.clone(), &node.phase); self.lifts_stack.push(Lifts::new()); diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 7225bfb9fd2..5fed221045d 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -3291,9 +3291,7 @@ impl<'a> TypeChecker<'a> { } fn type_check_class(&mut self, env: &mut SymbolEnv, stmt: &Stmt, ast_class: &AstClass) { - self - .ctx - .push_class(UserDefinedType::for_class(ast_class), &env.phase, None); + self.ctx.push_class(UserDefinedType::for_class(ast_class), &env.phase); // preflight classes cannot be declared inside an inflight scope // (the other way is okay) @@ -4289,10 +4287,10 @@ impl<'a> TypeChecker<'a> { types_map.insert(format!("{o}"), (*o, *n)); } - let mut new_env = SymbolEnv::new(None, SymbolEnvKind::Type(original_type), Phase::Independent, 0); + let dummy_env = SymbolEnv::new(None, SymbolEnvKind::Type(original_type), Phase::Independent, 0); let tt = Type::Class(Class { name: original_type_class.name.clone(), - env: new_env, + env: dummy_env, fqn: Some(original_fqn.to_string()), parent: original_type_class.parent, implements: original_type_class.implements.clone(), @@ -4306,9 +4304,12 @@ impl<'a> TypeChecker<'a> { // TODO: here we add a new type regardless whether we already "hydrated" `original_type` with these `type_params`. Cache! let mut new_type = self.types.add_type(tt); + let new_env = SymbolEnv::new(None, SymbolEnvKind::Type(new_type), Phase::Independent, 0); + let new_type_class = new_type.as_class_mut().unwrap(); - // Update the type's environment with the new type - new_type_class.env.kind = SymbolEnvKind::Type(new_type); + + // Update the class's env to point to the new env + new_type_class.env = new_env; // Add symbols from original type to new type // Note: this is currently limited to top-level function signatures and fields diff --git a/libs/wingc/src/type_check/symbol_env.rs b/libs/wingc/src/type_check/symbol_env.rs index e23cd61ceac..c15359c3421 100644 --- a/libs/wingc/src/type_check/symbol_env.rs +++ b/libs/wingc/src/type_check/symbol_env.rs @@ -156,12 +156,11 @@ pub struct SymbolLookupInfo { impl SymbolEnv { pub fn new(parent: Option, kind: SymbolEnvKind, phase: Phase, statement_idx: usize) -> Self { // Some sanity checks - // If parent is a type-environent this must be one too, otherwise it must not be + // If parent is a type-environent this must be one too assert!( - matches!(parent, Some(parent) if matches!(parent.kind, SymbolEnvKind::Type(_)) == matches!(kind, SymbolEnvKind::Type(_))) + parent.is_none() + || matches!(parent, Some(parent) if matches!(parent.kind, SymbolEnvKind::Type(_)) == matches!(kind, SymbolEnvKind::Type(_))) ); - // - //assert!(matches!(*return_type, Type::Void) || parent.is_some()); Self { symbol_map: BTreeMap::new(), From 175303edc8d92f5388645069480bf919fc6927e5 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 7 Sep 2023 14:12:23 +0300 Subject: [PATCH 07/56] wip --- libs/wingc/src/type_check.rs | 49 +++++++++++++++++----- libs/wingc/src/type_check/jsii_importer.rs | 3 ++ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 5fed221045d..7054c752dc7 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -91,7 +91,7 @@ pub enum VariableKind { Free, /// an instance member (either of classes or of structs) - InstanceMember, + InstanceMember(TypeRef), /// a class member (or an enum member) StaticMember, @@ -120,7 +120,9 @@ pub struct VariableInfo { } impl SymbolKind { + #[allow(clippy::too_many_arguments)] // TODO: refactor this pub fn make_member_variable( + member_of: TypeRef, name: Symbol, type_: TypeRef, reassignable: bool, @@ -137,7 +139,7 @@ impl SymbolKind { kind: if is_static { VariableKind::StaticMember } else { - VariableKind::InstanceMember + VariableKind::InstanceMember(member_of) }, access_modifier, docs, @@ -3173,6 +3175,7 @@ impl<'a> TypeChecker<'a> { match struct_env.define( &field.name, SymbolKind::make_member_variable( + struct_type, field.name.clone(), field_type, false, @@ -3264,6 +3267,7 @@ impl<'a> TypeChecker<'a> { match interface_env.define( method_name, SymbolKind::make_member_variable( + interface_type, method_name.clone(), method_type, false, @@ -3355,6 +3359,7 @@ impl<'a> TypeChecker<'a> { match class_env.define( &field.name, SymbolKind::make_member_variable( + class_type, field.name.clone(), field_type, field.reassignable, @@ -4091,7 +4096,7 @@ impl<'a> TypeChecker<'a> { &mut self, method_sig: &ast::FunctionSignature, env: &mut SymbolEnv, - instance_type: Option, + instance_type: Option, // TODO: change to bool, this can be inferred from the env (see `class_type` below) access_modifier: AccessModifier, class_env: &mut SymbolEnv, method_name: &Symbol, @@ -4103,9 +4108,14 @@ impl<'a> TypeChecker<'a> { .expect("Expected method type to be a function") .this_type = instance_type; + let SymbolEnvKind::Type(class_type) = class_env.kind else { + panic!("Expected class env to be a type"); + }; + match class_env.define( method_name, SymbolKind::make_member_variable( + class_type, method_name.clone(), method_type, false, @@ -4311,6 +4321,10 @@ impl<'a> TypeChecker<'a> { // Update the class's env to point to the new env new_type_class.env = new_env; + let SymbolEnvKind::Type(new_type) = new_type_class.env.kind else { // TODO: Ugly hack to get non mut ref of new_type so we can use it + panic!("Expected class env to be a type"); + }; + // Add symbols from original type to new type // Note: this is currently limited to top-level function signatures and fields for (name, symbol, _) in original_type_class.env.iter(true) { @@ -4358,6 +4372,7 @@ impl<'a> TypeChecker<'a> { // TODO: Original symbol is not available. SymbolKind::Variable should probably expose it &sym, SymbolKind::make_member_variable( + new_type, sym.clone(), self.types.add_type(Type::Function(new_sig)), *reassignable, @@ -4380,6 +4395,7 @@ impl<'a> TypeChecker<'a> { // TODO: Original symbol is not available. SymbolKind::Variable should probably expose it &var_name, SymbolKind::make_member_variable( + new_type, var_name.clone(), new_var_type, *reassignable, @@ -4658,9 +4674,12 @@ impl<'a> TypeChecker<'a> { let current_class_type = self .resolve_user_defined_type(¤t_class, env, self.ctx.current_stmt_idx()) .unwrap(); - // TODO: instance type is wrong here we type where property is defined (might be a super class) - private_access = current_class_type.is_same_type_as(&instance_type); - protected_access = private_access || current_class_type.is_strict_subtype_of(&instance_type); + // TODO: instance type is wrong here, we need the type where property is defined (might be a super class) + let VariableKind::InstanceMember(property_defined_in) = property_variable.kind else { + panic!("Expected property to be an instance member"); + }; + private_access = current_class_type.is_same_type_as(&property_defined_in); + protected_access = private_access || current_class_type.is_strict_subtype_of(&property_defined_in); } match property_variable.access_modifier { AccessModifier::Private => { @@ -4805,7 +4824,7 @@ impl<'a> TypeChecker<'a> { type_: instance_type, reassignable: false, phase: env.phase, - kind: VariableKind::InstanceMember, + kind: VariableKind::InstanceMember(instance_type), access_modifier: AccessModifier::Public, docs: None, }, @@ -4900,7 +4919,7 @@ impl<'a> TypeChecker<'a> { allow_static: bool, ) -> VariableInfo { let lookup_res = class.get_env().lookup_ext(property, None); - if let LookupResult::Found(field, _) = lookup_res { + if let LookupResult::Found(field, lookup_info) = lookup_res { let var = field.as_variable().expect("Expected property to be a variable"); if let VariableKind::StaticMember = var.kind { if allow_static { @@ -5011,8 +5030,12 @@ impl VisitorWithContext for TypeChecker<'_> { fn add_parent_members_to_struct_env( extends_types: &Vec, name: &Symbol, - struct_env: &mut SymbolEnv, + struct_env: &mut SymbolEnv, // TODO: pass the struct_type here and we'll extract the env ) -> Result<(), TypeError> { + let SymbolEnvKind::Type(struct_type) = struct_env.kind else { + panic!("Expected struct env"); + }; + // Add members of all parents to the struct's environment for parent_type in extends_types.iter() { let parent_struct = if let Some(parent_struct) = parent_type.as_struct() { @@ -5054,6 +5077,7 @@ fn add_parent_members_to_struct_env( struct_env.define( &sym, SymbolKind::make_member_variable( + struct_type, sym.clone(), member_type, false, @@ -5074,8 +5098,12 @@ fn add_parent_members_to_struct_env( fn add_parent_members_to_iface_env( extends_types: &Vec, name: &Symbol, - iface_env: &mut SymbolEnv, + iface_env: &mut SymbolEnv, // TODO: pass the iface_type here and we'll extract the env ) -> Result<(), TypeError> { + let SymbolEnvKind::Type(iface_type) = iface_env.kind else { + panic!("Expected interface env"); + }; + // Add members of all parents to the interface's environment for parent_type in extends_types.iter() { let parent_iface = if let Some(parent_iface) = parent_type.as_interface() { @@ -5117,6 +5145,7 @@ fn add_parent_members_to_iface_env( iface_env.define( &sym, SymbolKind::make_member_variable( + iface_type, sym.clone(), member_type, false, diff --git a/libs/wingc/src/type_check/jsii_importer.rs b/libs/wingc/src/type_check/jsii_importer.rs index 2672b62a5d2..17d4ad1f26c 100644 --- a/libs/wingc/src/type_check/jsii_importer.rs +++ b/libs/wingc/src/type_check/jsii_importer.rs @@ -502,6 +502,7 @@ impl<'a> JsiiImporter<'a> { .define( &sym, SymbolKind::make_member_variable( + wing_type, sym.clone(), method_sig, false, @@ -546,6 +547,7 @@ impl<'a> JsiiImporter<'a> { .define( &sym, SymbolKind::make_member_variable( + wing_type, sym.clone(), wing_type, !matches!(p.immutable, Some(true)), @@ -769,6 +771,7 @@ impl<'a> JsiiImporter<'a> { if let Err(e) = class_env.define( &sym, SymbolKind::make_member_variable( + new_type, sym.clone(), method_sig, false, From 0b49843421ae6f1856f4b6dabf711d6528fa0808 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 7 Sep 2023 21:45:29 +0300 Subject: [PATCH 08/56] wip --- libs/wingc/src/type_check.rs | 48 +++++++++------------- libs/wingc/src/type_check/jsii_importer.rs | 3 -- 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 7054c752dc7..f2b5a6baf81 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -91,7 +91,7 @@ pub enum VariableKind { Free, /// an instance member (either of classes or of structs) - InstanceMember(TypeRef), + InstanceMember, /// a class member (or an enum member) StaticMember, @@ -122,7 +122,6 @@ pub struct VariableInfo { impl SymbolKind { #[allow(clippy::too_many_arguments)] // TODO: refactor this pub fn make_member_variable( - member_of: TypeRef, name: Symbol, type_: TypeRef, reassignable: bool, @@ -139,7 +138,7 @@ impl SymbolKind { kind: if is_static { VariableKind::StaticMember } else { - VariableKind::InstanceMember(member_of) + VariableKind::InstanceMember }, access_modifier, docs, @@ -3175,7 +3174,6 @@ impl<'a> TypeChecker<'a> { match struct_env.define( &field.name, SymbolKind::make_member_variable( - struct_type, field.name.clone(), field_type, false, @@ -3267,7 +3265,6 @@ impl<'a> TypeChecker<'a> { match interface_env.define( method_name, SymbolKind::make_member_variable( - interface_type, method_name.clone(), method_type, false, @@ -3359,7 +3356,6 @@ impl<'a> TypeChecker<'a> { match class_env.define( &field.name, SymbolKind::make_member_variable( - class_type, field.name.clone(), field_type, field.reassignable, @@ -4108,14 +4104,9 @@ impl<'a> TypeChecker<'a> { .expect("Expected method type to be a function") .this_type = instance_type; - let SymbolEnvKind::Type(class_type) = class_env.kind else { - panic!("Expected class env to be a type"); - }; - match class_env.define( method_name, SymbolKind::make_member_variable( - class_type, method_name.clone(), method_type, false, @@ -4372,7 +4363,6 @@ impl<'a> TypeChecker<'a> { // TODO: Original symbol is not available. SymbolKind::Variable should probably expose it &sym, SymbolKind::make_member_variable( - new_type, sym.clone(), self.types.add_type(Type::Function(new_sig)), *reassignable, @@ -4395,7 +4385,6 @@ impl<'a> TypeChecker<'a> { // TODO: Original symbol is not available. SymbolKind::Variable should probably expose it &var_name, SymbolKind::make_member_variable( - new_type, var_name.clone(), new_var_type, *reassignable, @@ -4674,9 +4663,16 @@ impl<'a> TypeChecker<'a> { let current_class_type = self .resolve_user_defined_type(¤t_class, env, self.ctx.current_stmt_idx()) .unwrap(); - // TODO: instance type is wrong here, we need the type where property is defined (might be a super class) - let VariableKind::InstanceMember(property_defined_in) = property_variable.kind else { - panic!("Expected property to be an instance member"); + // Lookup the property in the class env to find out in which class (peraps an ancestor) it was defined + let SymbolEnvKind::Type(property_defined_in) = current_class_type + .as_class() + .expect("current class to be a class") + .env + .lookup_ext(&property, None) + .expect("property to be in class") + .1 + .env.kind else { + panic!("Expected class env to be a type"); }; private_access = current_class_type.is_same_type_as(&property_defined_in); protected_access = private_access || current_class_type.is_strict_subtype_of(&property_defined_in); @@ -4824,7 +4820,7 @@ impl<'a> TypeChecker<'a> { type_: instance_type, reassignable: false, phase: env.phase, - kind: VariableKind::InstanceMember(instance_type), + kind: VariableKind::InstanceMember, access_modifier: AccessModifier::Public, docs: None, }, @@ -4911,7 +4907,7 @@ impl<'a> TypeChecker<'a> { } } - /// Get's the type of an instance variable in a class + /// Get's the type of an instance variable in a class and the type in which it's defined fn get_property_from_class_like( &mut self, class: &impl ClassLike, @@ -4919,12 +4915,16 @@ impl<'a> TypeChecker<'a> { allow_static: bool, ) -> VariableInfo { let lookup_res = class.get_env().lookup_ext(property, None); - if let LookupResult::Found(field, lookup_info) = lookup_res { + if let LookupResult::Found(field, _) = lookup_res { let var = field.as_variable().expect("Expected property to be a variable"); + // let SymbolEnvKind::Type(def_type) = lookup_info.env.kind else { // TODO: make an "as_type_env" method + // panic!("Expected env to be a type env"); + // }; if let VariableKind::StaticMember = var.kind { if allow_static { return var.clone(); } + self .spanned_error_with_var( property, @@ -5032,10 +5032,6 @@ fn add_parent_members_to_struct_env( name: &Symbol, struct_env: &mut SymbolEnv, // TODO: pass the struct_type here and we'll extract the env ) -> Result<(), TypeError> { - let SymbolEnvKind::Type(struct_type) = struct_env.kind else { - panic!("Expected struct env"); - }; - // Add members of all parents to the struct's environment for parent_type in extends_types.iter() { let parent_struct = if let Some(parent_struct) = parent_type.as_struct() { @@ -5077,7 +5073,6 @@ fn add_parent_members_to_struct_env( struct_env.define( &sym, SymbolKind::make_member_variable( - struct_type, sym.clone(), member_type, false, @@ -5100,10 +5095,6 @@ fn add_parent_members_to_iface_env( name: &Symbol, iface_env: &mut SymbolEnv, // TODO: pass the iface_type here and we'll extract the env ) -> Result<(), TypeError> { - let SymbolEnvKind::Type(iface_type) = iface_env.kind else { - panic!("Expected interface env"); - }; - // Add members of all parents to the interface's environment for parent_type in extends_types.iter() { let parent_iface = if let Some(parent_iface) = parent_type.as_interface() { @@ -5145,7 +5136,6 @@ fn add_parent_members_to_iface_env( iface_env.define( &sym, SymbolKind::make_member_variable( - iface_type, sym.clone(), member_type, false, diff --git a/libs/wingc/src/type_check/jsii_importer.rs b/libs/wingc/src/type_check/jsii_importer.rs index 17d4ad1f26c..2672b62a5d2 100644 --- a/libs/wingc/src/type_check/jsii_importer.rs +++ b/libs/wingc/src/type_check/jsii_importer.rs @@ -502,7 +502,6 @@ impl<'a> JsiiImporter<'a> { .define( &sym, SymbolKind::make_member_variable( - wing_type, sym.clone(), method_sig, false, @@ -547,7 +546,6 @@ impl<'a> JsiiImporter<'a> { .define( &sym, SymbolKind::make_member_variable( - wing_type, sym.clone(), wing_type, !matches!(p.immutable, Some(true)), @@ -771,7 +769,6 @@ impl<'a> JsiiImporter<'a> { if let Err(e) = class_env.define( &sym, SymbolKind::make_member_variable( - new_type, sym.clone(), method_sig, false, From 9c187a21ddc92ba44cc1599300baf53c4250a40d Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 7 Sep 2023 23:23:11 +0300 Subject: [PATCH 09/56] wip --- libs/wingc/src/type_check.rs | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index f2b5a6baf81..d51a2124bd0 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -3527,7 +3527,7 @@ impl<'a> TypeChecker<'a> { //let return_type_inferred = self.update_known_inferences(&mut env.return_type, &stmt.span); // Make sure we're inside a function - let Some((_, current_func_sig)) = self.ctx.current_method() else { + let Some((_, current_func_sig)) = self.ctx.current_function() else { self.spanned_error(stmt, "Return statement outside of function cannot return a value"); return; }; @@ -4664,16 +4664,7 @@ impl<'a> TypeChecker<'a> { .resolve_user_defined_type(¤t_class, env, self.ctx.current_stmt_idx()) .unwrap(); // Lookup the property in the class env to find out in which class (peraps an ancestor) it was defined - let SymbolEnvKind::Type(property_defined_in) = current_class_type - .as_class() - .expect("current class to be a class") - .env - .lookup_ext(&property, None) - .expect("property to be in class") - .1 - .env.kind else { - panic!("Expected class env to be a type"); - }; + let property_defined_in = self.get_definition_type(instance_type, property); private_access = current_class_type.is_same_type_as(&property_defined_in); protected_access = private_access || current_class_type.is_strict_subtype_of(&property_defined_in); } @@ -5019,8 +5010,28 @@ impl<'a> TypeChecker<'a> { (None, None) } } + + /// Returns the type in which the property is defined (this might be any class like type). It might + /// be either the passed `instance_type` or one of its ancestors. + fn get_definition_type(&self, instance_type: UnsafeRef, property: &Symbol) -> UnsafeRef { + let class_like_env= match &*instance_type { + Type::Class(c) => &c.env, + Type::Interface(i) => &i.env, + Type::Struct(s) => &s.env, + _ => panic!("Expected instance type to be a class like type"), + }; + let SymbolEnvKind::Type(property_defined_in) = class_like_env + .lookup_ext(property, None) + .expect(&format!("property {property} to be in class {instance_type}")) + .1 + .env.kind else { + panic!("Expected class env to be a type"); + }; + property_defined_in + } } + impl VisitorWithContext for TypeChecker<'_> { fn ctx(&mut self) -> &mut VisitContext { &mut self.ctx From 9deda88b2ff961d888a03977bfccff47f0d9fb2a Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Fri, 8 Sep 2023 19:48:29 +0300 Subject: [PATCH 10/56] wip --- libs/wingc/src/type_check.rs | 105 ++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 44 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index d51a2124bd0..b568789cbbe 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -2516,7 +2516,10 @@ impl<'a> TypeChecker<'a> { // Create an environment for the function let mut function_env = self.types.add_symbol_env(SymbolEnv::new( Some(env.get_ref()), - SymbolEnvKind::Function { is_init: false }, + SymbolEnvKind::Function { + is_init: false, + sig: function_type, + }, func_def.signature.phase, self.ctx.current_stmt_idx(), )); @@ -2812,15 +2815,17 @@ impl<'a> TypeChecker<'a> { self.ctx = ctx; self.type_check_scope(scope); } - // if matches!(env.kind, SymbolEnvKind::Function { .. }) { - // if let Type::Inferred(n) = &*env.return_type { - // if self.types.get_inference_by_id(*n).is_none() { - // // If function types don't return anything then we should set the return type to void - // self.types.update_inferred_type(*n, self.types.void(), &scope.span); - // } - // self.update_known_inferences(&mut env.return_type, &scope.span); - // } - // } + + if let SymbolEnvKind::Function { sig, .. } = env.kind { + let mut return_type = sig.as_function_sig().expect("a fucntion type").return_type; + if let Type::Inferred(n) = &*return_type { + if self.types.get_inference_by_id(*n).is_none() { + // If function types don't return anything then we should set the return type to void + self.types.update_inferred_type(*n, self.types.void(), &scope.span); + } + self.update_known_inferences(&mut return_type, &scope.span); + } + } for symbol_data in env.symbol_map.values_mut() { if let SymbolKind::Variable(ref mut var_info) = symbol_data.1 { @@ -2968,7 +2973,7 @@ impl<'a> TypeChecker<'a> { initial_value, type_, } => { - tc.type_check_let(type_, env, initial_value, var_name, reassignable, stmt); + tc.type_check_let(type_, env, initial_value, var_name, reassignable, stmt); // TODO: do we now need to pass stmt everywhere when we can get it from the ctx? } StmtKind::ForLoop { iterator, @@ -3524,22 +3529,27 @@ impl<'a> TypeChecker<'a> { } fn type_check_return(&mut self, env: &mut SymbolEnv, stmt: &Stmt, exp: &Option) { - //let return_type_inferred = self.update_known_inferences(&mut env.return_type, &stmt.span); - // Make sure we're inside a function - let Some((_, current_func_sig)) = self.ctx.current_function() else { - self.spanned_error(stmt, "Return statement outside of function cannot return a value"); - return; - }; + if self.ctx.current_function().is_none() { + self.spanned_error(stmt, "Return statement outside of function cannot return a value"); + return; + }; + + let cur_func_env = *self.ctx.current_function_env().expect("a function env"); + let SymbolEnvKind::Function{sig: cur_func_type, ..} = cur_func_env.kind else { + panic!("Expected function env"); + }; + let mut function_ret_type = cur_func_type.as_function_sig().expect("a function_type").return_type; // Get the expected return type, we need to look it up in the parent of the current function's env - let function_def_env = self - .ctx - .current_function_env() - .expect("Expected to be in a function") - .parent - .expect("Function is defined in an env"); - let mut function_ret_type = self.resolve_type_annotation(¤t_func_sig.return_type, &function_def_env); + // let function_def_env = self + // .ctx + // .current_function_env() + // .expect("Expected to be in a function") + // .parent + // .expect("Function is defined in an env"); + //let mut function_ret_type = self.resolve_type_annotation(¤t_func_sig.return_type, &function_def_env); + let return_type_inferred = self.update_known_inferences(&mut function_ret_type, &stmt.span); if let Some(return_expression) = exp { let (return_type, _) = self.type_check_exp(return_expression, env); @@ -3547,14 +3557,14 @@ impl<'a> TypeChecker<'a> { if !function_ret_type.is_void() { self.validate_type(return_type, function_ret_type, return_expression); } else { - //if return_type_inferred { - self.spanned_error(stmt, "Unexpected return value from void function"); - // } else { - // self.spanned_error( - // stmt, - // "Unexpected return value from void function. Return type annotations are required for methods.", - // ); - // } + if return_type_inferred { + self.spanned_error(stmt, "Unexpected return value from void function"); + } else { + self.spanned_error( + stmt, + "Unexpected return value from void function. Return type annotations are required for methods.", + ); + } } } else { self.validate_type(self.types.void(), function_ret_type, stmt); @@ -3612,9 +3622,9 @@ impl<'a> TypeChecker<'a> { self.spanned_error( stmt, format!( - "Cannot bring \"{}\" - modules with statements besides classes, interfaces, enums, and structs cannot be brought", - name - ), + "Cannot bring \"{}\" - modules with statements besides classes, interfaces, enums, and structs cannot be brought", + name + ), ); return; } @@ -3940,8 +3950,11 @@ impl<'a> TypeChecker<'a> { // Create a temp init environment to use for typechecking args let init_env = &mut SymbolEnv::new( - Some(class_env.get_ref()), - SymbolEnvKind::Function { is_init: true }, + Some(class_env.get_ref()), // TODO: this doesn't make sense, the class_env is a type's env and we're creating an env for a function! + SymbolEnvKind::Function { + is_init: true, + sig: *class_initializer, + }, class_env.phase, scope.statements[0].idx, ); @@ -4052,7 +4065,10 @@ impl<'a> TypeChecker<'a> { let is_init = method_name.name == CLASS_INIT_NAME || method_name.name == CLASS_INFLIGHT_INIT_NAME; let mut method_env = self.types.add_symbol_env(SymbolEnv::new( Some(parent_env.get_ref()), - SymbolEnvKind::Function { is_init }, + SymbolEnvKind::Function { + is_init, + sig: method_type, + }, method_sig.phase, statement_idx, )); @@ -5014,24 +5030,23 @@ impl<'a> TypeChecker<'a> { /// Returns the type in which the property is defined (this might be any class like type). It might /// be either the passed `instance_type` or one of its ancestors. fn get_definition_type(&self, instance_type: UnsafeRef, property: &Symbol) -> UnsafeRef { - let class_like_env= match &*instance_type { + let class_like_env = match &*instance_type { Type::Class(c) => &c.env, Type::Interface(i) => &i.env, Type::Struct(s) => &s.env, _ => panic!("Expected instance type to be a class like type"), }; - let SymbolEnvKind::Type(property_defined_in) = class_like_env + let SymbolEnvKind::Type(property_defined_in) = class_like_env .lookup_ext(property, None) .expect(&format!("property {property} to be in class {instance_type}")) .1 - .env.kind else { + .env.kind else { panic!("Expected class env to be a type"); }; - property_defined_in + property_defined_in } } - impl VisitorWithContext for TypeChecker<'_> { fn ctx(&mut self) -> &mut VisitContext { &mut self.ctx @@ -5323,7 +5338,9 @@ pub fn fully_qualify_std_type(type_: &str) -> String { match type_name { "Json" | "MutJson" | "MutArray" | "MutMap" | "MutSet" | "Array" | "Map" | "Set" | "String" | "Duration" - | "Boolean" | "Number" => format!("{WINGSDK_STD_MODULE}.{type_name}"), + | "Boolean" | "Number" => { + format!("{WINGSDK_STD_MODULE}.{type_name}") + } _ => type_name.to_string(), } } From d2bce2f3b558e11c2854f9425258cb1afa9e2d57 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Fri, 8 Sep 2023 19:48:44 +0300 Subject: [PATCH 11/56] wip --- libs/wingc/src/type_check/symbol_env.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/wingc/src/type_check/symbol_env.rs b/libs/wingc/src/type_check/symbol_env.rs index c15359c3421..c23c54f5c62 100644 --- a/libs/wingc/src/type_check/symbol_env.rs +++ b/libs/wingc/src/type_check/symbol_env.rs @@ -30,7 +30,7 @@ pub struct SymbolEnv { pub enum SymbolEnvKind { Scope, - Function { is_init: bool }, + Function { is_init: bool, sig: TypeRef }, Type(TypeRef), } @@ -266,7 +266,7 @@ impl SymbolEnv { kind, SymbolLookupInfo { phase: self.phase, - init: matches!(self.kind, SymbolEnvKind::Function { is_init: true }), + init: matches!(self.kind, SymbolEnvKind::Function { is_init: true, .. }), env: get_ref, }, ); @@ -388,7 +388,7 @@ impl<'a> Iterator for SymbolEnvIter<'a> { kind, SymbolLookupInfo { phase: self.curr_env.phase, - init: matches!(self.curr_env.kind, SymbolEnvKind::Function { is_init: true }), + init: matches!(self.curr_env.kind, SymbolEnvKind::Function { is_init: true, .. }), env: self.curr_env.get_ref(), }, )) From 011c9da0b1c19c446e514ffdee04f83e608d18a7 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sat, 9 Sep 2023 13:39:22 +0300 Subject: [PATCH 12/56] static support --- libs/wingc/src/type_check.rs | 74 +++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index b568789cbbe..fcf1153e994 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -4672,37 +4672,8 @@ impl<'a> TypeChecker<'a> { let mut property_variable = self.resolve_variable_from_instance_type(instance_type, property, env, object); - // TODO: Here we can get the access_modifier of the property and check it based on the current class - let mut private_access = false; - let mut protected_access = false; - if let Some(current_class) = self.ctx.current_class().map(|udt| udt.clone()) { - let current_class_type = self - .resolve_user_defined_type(¤t_class, env, self.ctx.current_stmt_idx()) - .unwrap(); - // Lookup the property in the class env to find out in which class (peraps an ancestor) it was defined - let property_defined_in = self.get_definition_type(instance_type, property); - private_access = current_class_type.is_same_type_as(&property_defined_in); - protected_access = private_access || current_class_type.is_strict_subtype_of(&property_defined_in); - } - match property_variable.access_modifier { - AccessModifier::Private => { - if !private_access { - self.spanned_error( - property, - format!("Cannot access private member {property} of {instance_type}"), - ); - } - } - AccessModifier::Protected => { - if !protected_access { - self.spanned_error( - property, - format!("Cannot access protected member {property} of {instance_type}"), - ); - } - } - AccessModifier::Public => {} // keep this here to make sure we don't add a new access modifier without handling it here - } + // Validate access modifier + self.check_access(env, instance_type, property, property_variable.access_modifier); // if the object is `this`, then use the property's phase instead of the object phase let property_phase = if property_variable.phase == Phase::Independent { @@ -4788,6 +4759,8 @@ impl<'a> TypeChecker<'a> { Type::Class(ref c) => match c.env.lookup(&property, None) { Some(SymbolKind::Variable(v)) => { if let VariableKind::StaticMember = v.kind { + // Validate access modifier + self.check_access(env, type_, property, v.access_modifier); (v.clone(), v.phase) } else { self.spanned_error_with_var( @@ -4810,6 +4783,45 @@ impl<'a> TypeChecker<'a> { } } + /// Check if the given property on the given type with the given access modifier can be accessed from the current context + fn check_access( + &mut self, + env: &mut SymbolEnv, + type_: UnsafeRef, + property: &Symbol, + allowed_access: AccessModifier, + ) { + // Determine the access type of the property + let mut private_access = false; + let mut protected_access = false; + if let Some(current_class) = self.ctx.current_class().map(|udt| udt.clone()) { + let current_class_type = self + .resolve_user_defined_type(¤t_class, env, self.ctx.current_stmt_idx()) + .unwrap(); + // Lookup the property in the class env to find out in which class (perhaps an ancestor) it was defined + let property_defined_in = self.get_definition_type(type_, property); + private_access = current_class_type.is_same_type_as(&property_defined_in); + protected_access = private_access || current_class_type.is_strict_subtype_of(&property_defined_in); + } + // Compare the access type with what's allowed + match allowed_access { + AccessModifier::Private => { + if !private_access { + self.spanned_error(property, format!("Cannot access private member {property} of {type_}")); + } + } + AccessModifier::Protected => { + if !protected_access { + self.spanned_error( + property, + format!("Cannot access protected member {property} of {type_}"), + ); + } + } + AccessModifier::Public => {} // keep this here to make sure we don't add a new access modifier without handling it here + } + } + fn resolve_variable_from_instance_type( &mut self, instance_type: TypeRef, From b2f895bc0730235a93eb3d9bb22419c5918b34b8 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sat, 9 Sep 2023 13:50:57 +0300 Subject: [PATCH 13/56] added test --- examples/tests/invalid/access_modifiers.w | 88 +++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 examples/tests/invalid/access_modifiers.w diff --git a/examples/tests/invalid/access_modifiers.w b/examples/tests/invalid/access_modifiers.w new file mode 100644 index 00000000000..0baa4830a67 --- /dev/null +++ b/examples/tests/invalid/access_modifiers.w @@ -0,0 +1,88 @@ +class Foo { + protected protected_field: str; + private_field: str; + pub public_field: str; + + init() { + this.protected_field = "hello"; + this.private_field = "world"; + this.public_field = "!"; + } + + method() { + // All of these are valid + log(this.protected_field); + log(this.private_field); + log(this.public_field); + this.public_method(); + this.protected_method(); + this.private_method(); + } + + pub public_method() {} + protected protected_method() {} + private_method() {} + + pub static public_static_method() {} + protected static protected_static_method() {} + static private_static_method() {} +} + +class Bar extends Foo { + method() { + // Check protected access + log(this.protected_field); + log(this.private_field); + // ^ Cannot access private member + log(this.public_field); + this.public_method(); + this.protected_method(); + this.private_method(); + // ^ Cannot access private member + } + + static static_method() { + // Check static protected access + Foo.public_static_method(); + Foo.protected_static_method(); + Foo.private_static_method(); + // ^ Cannot access private member + } +} + +let foo = new Foo(); +// Chck access from non class +log(foo.protected_field); +// ^ Cannot access protected member +log(foo.private_field); +// ^ Cannot access private member +log(foo.public_field); +Foo.public_static_method(); +Foo.protected_static_method(); +// ^ Cannot access protected member +Foo.private_static_method(); +// ^ Cannot access private member + +// Check access from non child class (protected is not allowed) +class BarBar { + method() { + log(foo.protected_field); + // ^ Cannot access protected member + log(foo.private_field); + // ^ Cannot access private member + log(foo.public_field); + foo.public_method(); + foo.protected_method(); + // ^ Cannot access protected member + foo.private_method(); + // ^ Cannot access private member + } + + static static_method() { + Foo.public_static_method(); + Foo.protected_static_method(); + // ^ Cannot access protected member + Foo.private_static_method(); + // ^ Cannot access private member + } +} From 67c380c945c213b9ee0a53384a7d5a7b5e9fde3a Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sat, 9 Sep 2023 14:30:10 +0300 Subject: [PATCH 14/56] correct env for super call, avoid cascading error for unknown properties --- libs/wingc/src/type_check.rs | 51 +++++++----------------------------- 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index fcf1153e994..477d23d5cca 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -3925,10 +3925,10 @@ impl<'a> TypeChecker<'a> { &mut self, scope: &Scope, class_type: TypeRef, - class_env: &mut SymbolEnv, + env: &mut SymbolEnv, init_name: &str, ) { - if &scope.statements.len() >= &1 { + if scope.statements.len() >= 1 { match &scope.statements[0].kind { StmtKind::SuperConstructor { arg_list } => { if let Some(parent_class) = &class_type.as_class().unwrap().parent { @@ -3940,44 +3940,7 @@ impl<'a> TypeChecker<'a> { .collect_vec()[0] .1; - let class_initializer = &class_type - .as_class() - .unwrap() - .methods(true) - .filter(|(name, _type)| name == init_name) - .collect_vec()[0] - .1; - - // Create a temp init environment to use for typechecking args - let init_env = &mut SymbolEnv::new( - Some(class_env.get_ref()), // TODO: this doesn't make sense, the class_env is a type's env and we're creating an env for a function! - SymbolEnvKind::Function { - is_init: true, - sig: *class_initializer, - }, - class_env.phase, - scope.statements[0].idx, - ); - - // add the initializer args to the init_env - for arg in class_initializer.as_function_sig().unwrap().parameters.iter() { - let sym = Symbol { - name: arg.name.clone(), - span: scope.statements[0].span.clone(), - }; - match init_env.define( - &sym, - SymbolKind::make_free_variable(sym.clone(), arg.typeref, false, init_env.phase), - StatementIdx::Top, - ) { - Err(type_error) => { - self.type_error(type_error); - } - _ => {} - }; - } - - let arg_list_types = self.type_check_arg_list(&arg_list, init_env); + let arg_list_types = self.type_check_arg_list(&arg_list, env); self.type_check_arg_list_against_function_sig( &arg_list, parent_initializer.as_function_sig().unwrap(), @@ -4673,7 +4636,9 @@ impl<'a> TypeChecker<'a> { let mut property_variable = self.resolve_variable_from_instance_type(instance_type, property, env, object); // Validate access modifier - self.check_access(env, instance_type, property, property_variable.access_modifier); + if !property_variable.type_.is_unresolved() { + self.check_access(env, instance_type, property, property_variable.access_modifier); + } // if the object is `this`, then use the property's phase instead of the object phase let property_phase = if property_variable.phase == Phase::Independent { @@ -4760,7 +4725,9 @@ impl<'a> TypeChecker<'a> { Some(SymbolKind::Variable(v)) => { if let VariableKind::StaticMember = v.kind { // Validate access modifier - self.check_access(env, type_, property, v.access_modifier); + if !v.type_.is_unresolved() { + self.check_access(env, type_, property, v.access_modifier); + } (v.clone(), v.phase) } else { self.spanned_error_with_var( From 3e2df56eca69a46ad40f8de15b8fa19d7a50b04a Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sat, 9 Sep 2023 14:42:54 +0300 Subject: [PATCH 15/56] type check return expr even when return statement is misplaced --- libs/wingc/src/type_check.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 477d23d5cca..18d78213a0b 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -3529,6 +3529,9 @@ impl<'a> TypeChecker<'a> { } fn type_check_return(&mut self, env: &mut SymbolEnv, stmt: &Stmt, exp: &Option) { + // Type check the return expression + let return_type = exp.as_ref().map(|exp| (self.type_check_exp(exp, env).0, exp)); + // Make sure we're inside a function if self.ctx.current_function().is_none() { self.spanned_error(stmt, "Return statement outside of function cannot return a value"); @@ -3541,19 +3544,9 @@ impl<'a> TypeChecker<'a> { }; let mut function_ret_type = cur_func_type.as_function_sig().expect("a function_type").return_type; - // Get the expected return type, we need to look it up in the parent of the current function's env - // let function_def_env = self - // .ctx - // .current_function_env() - // .expect("Expected to be in a function") - // .parent - // .expect("Function is defined in an env"); - //let mut function_ret_type = self.resolve_type_annotation(¤t_func_sig.return_type, &function_def_env); let return_type_inferred = self.update_known_inferences(&mut function_ret_type, &stmt.span); - if let Some(return_expression) = exp { - let (return_type, _) = self.type_check_exp(return_expression, env); - + if let Some((return_type, return_expression)) = return_type { if !function_ret_type.is_void() { self.validate_type(return_type, function_ret_type, return_expression); } else { From a14c56f929987caa548d15dc956d4095439ce180 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 10:22:29 +0300 Subject: [PATCH 16/56] correctly handle access check to std lib type properties (Array) --- libs/wingc/src/type_check.rs | 188 +++++++++++++++++------------------ 1 file changed, 93 insertions(+), 95 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 18d78213a0b..318236f8c8e 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -362,7 +362,7 @@ impl Display for Interface { type ClassLikeIterator<'a> = FilterMap, fn(::Item) -> Option<(String, TypeRef)>>; -pub trait ClassLike { +pub trait ClassLike: Display { fn get_env(&self) -> &SymbolEnv; fn methods(&self, with_ancestry: bool) -> ClassLikeIterator<'_> { @@ -450,6 +450,12 @@ pub struct Struct { pub env: SymbolEnv, } +impl Display for Struct { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.name.name) + } +} + #[derive(Debug)] pub struct Enum { pub name: Symbol, @@ -4629,9 +4635,11 @@ impl<'a> TypeChecker<'a> { let mut property_variable = self.resolve_variable_from_instance_type(instance_type, property, env, object); // Validate access modifier - if !property_variable.type_.is_unresolved() { - self.check_access(env, instance_type, property, property_variable.access_modifier); - } + // if !property_variable.type_.is_unresolved() { + // // TODO: this isn't good enough becaues `instance_type` might be an array so we need to "actual" class_type (Array). This is done for us in + // // `resolve_variable_from_instance_type`, fixing this might also make the unresolved check above redundant + // self.check_access(env, instance_type, property, property_variable.access_modifier); + // } // if the object is `this`, then use the property's phase instead of the object phase let property_phase = if property_variable.phase == Phase::Independent { @@ -4711,32 +4719,42 @@ impl<'a> TypeChecker<'a> { } let new_class = self.hydrate_class_type_arguments(env, WINGSDK_STRUCT, vec![type_]); - let v = self.get_property_from_class_like(new_class.as_class().unwrap(), property, true); + let v = self.get_property_from_class_like(new_class.as_class().unwrap(), property, true, env); (v, Phase::Independent) } - Type::Class(ref c) => match c.env.lookup(&property, None) { - Some(SymbolKind::Variable(v)) => { - if let VariableKind::StaticMember = v.kind { - // Validate access modifier - if !v.type_.is_unresolved() { - self.check_access(env, type_, property, v.access_modifier); - } - (v.clone(), v.phase) - } else { - self.spanned_error_with_var( - property, - format!( - "Class \"{}\" contains a member \"{}\" but it is not static", - type_, property.name - ), - ) - } + Type::Class(ref c) => + /*match c.env.lookup(&property, None)*/ + { + let v = self.get_property_from_class_like(c, property, true, env); + if matches!(v.kind, VariableKind::InstanceMember) { + return self.spanned_error_with_var( + property, + format!("Class \"{c}\" contains a member \"{property}\" but it is not static"), + ); } - _ => self.spanned_error_with_var( - property, - format!("No member \"{}\" in class \"{}\"", property.name, type_), - ), - }, + (v.clone(), v.phase) + // Some(SymbolKind::Variable(v)) => { + // if let VariableKind::StaticMember = v.kind { + // // Validate access modifier + // if !v.type_.is_unresolved() { + // self.check_access(env, type_, property, v.access_modifier); + // } + // (v.clone(), v.phase) + // } else { + // self.spanned_error_with_var( + // property, + // format!( + // "Class \"{}\" contains a member \"{}\" but it is not static", + // type_, property.name + // ), + // ) + // } + // } + // _ => self.spanned_error_with_var( + // property, + // format!("No member \"{}\" in class \"{}\"", property.name, type_), + // ), + } _ => self.spanned_error_with_var(property, format!("\"{}\" not a valid reference", reference)), } } @@ -4744,43 +4762,6 @@ impl<'a> TypeChecker<'a> { } /// Check if the given property on the given type with the given access modifier can be accessed from the current context - fn check_access( - &mut self, - env: &mut SymbolEnv, - type_: UnsafeRef, - property: &Symbol, - allowed_access: AccessModifier, - ) { - // Determine the access type of the property - let mut private_access = false; - let mut protected_access = false; - if let Some(current_class) = self.ctx.current_class().map(|udt| udt.clone()) { - let current_class_type = self - .resolve_user_defined_type(¤t_class, env, self.ctx.current_stmt_idx()) - .unwrap(); - // Lookup the property in the class env to find out in which class (perhaps an ancestor) it was defined - let property_defined_in = self.get_definition_type(type_, property); - private_access = current_class_type.is_same_type_as(&property_defined_in); - protected_access = private_access || current_class_type.is_strict_subtype_of(&property_defined_in); - } - // Compare the access type with what's allowed - match allowed_access { - AccessModifier::Private => { - if !private_access { - self.spanned_error(property, format!("Cannot access private member {property} of {type_}")); - } - } - AccessModifier::Protected => { - if !protected_access { - self.spanned_error( - property, - format!("Cannot access protected member {property} of {type_}"), - ); - } - } - AccessModifier::Public => {} // keep this here to make sure we don't add a new access modifier without handling it here - } - } fn resolve_variable_from_instance_type( &mut self, @@ -4792,8 +4773,8 @@ impl<'a> TypeChecker<'a> { ) -> VariableInfo { match *instance_type { Type::Optional(t) => self.resolve_variable_from_instance_type(t, property, env, _object), - Type::Class(ref class) => self.get_property_from_class_like(class, property, false), - Type::Interface(ref interface) => self.get_property_from_class_like(interface, property, false), + Type::Class(ref class) => self.get_property_from_class_like(class, property, false, env), + Type::Interface(ref interface) => self.get_property_from_class_like(interface, property, false, env), Type::Anything => VariableInfo { name: property.clone(), type_: instance_type, @@ -4807,27 +4788,27 @@ impl<'a> TypeChecker<'a> { // Lookup wingsdk std types, hydrating generics if necessary Type::Array(t) => { let new_class = self.hydrate_class_type_arguments(env, WINGSDK_ARRAY, vec![t]); - self.get_property_from_class_like(new_class.as_class().unwrap(), property, false) + self.get_property_from_class_like(new_class.as_class().unwrap(), property, false, env) } Type::MutArray(t) => { let new_class = self.hydrate_class_type_arguments(env, WINGSDK_MUT_ARRAY, vec![t]); - self.get_property_from_class_like(new_class.as_class().unwrap(), property, false) + self.get_property_from_class_like(new_class.as_class().unwrap(), property, false, env) } Type::Set(t) => { let new_class = self.hydrate_class_type_arguments(env, WINGSDK_SET, vec![t]); - self.get_property_from_class_like(new_class.as_class().unwrap(), property, false) + self.get_property_from_class_like(new_class.as_class().unwrap(), property, false, env) } Type::MutSet(t) => { let new_class = self.hydrate_class_type_arguments(env, WINGSDK_MUT_SET, vec![t]); - self.get_property_from_class_like(new_class.as_class().unwrap(), property, false) + self.get_property_from_class_like(new_class.as_class().unwrap(), property, false, env) } Type::Map(t) => { let new_class = self.hydrate_class_type_arguments(env, WINGSDK_MAP, vec![t]); - self.get_property_from_class_like(new_class.as_class().unwrap(), property, false) + self.get_property_from_class_like(new_class.as_class().unwrap(), property, false, env) } Type::MutMap(t) => { let new_class = self.hydrate_class_type_arguments(env, WINGSDK_MUT_MAP, vec![t]); - self.get_property_from_class_like(new_class.as_class().unwrap(), property, false) + self.get_property_from_class_like(new_class.as_class().unwrap(), property, false, env) } Type::Json(_) => self.get_property_from_class_like( env @@ -4840,6 +4821,7 @@ impl<'a> TypeChecker<'a> { .unwrap(), property, false, + env, ), Type::MutJson => self.get_property_from_class_like( env @@ -4852,6 +4834,7 @@ impl<'a> TypeChecker<'a> { .unwrap(), property, false, + env, ), Type::String => self.get_property_from_class_like( env @@ -4864,6 +4847,7 @@ impl<'a> TypeChecker<'a> { .unwrap(), property, false, + env, ), Type::Duration => self.get_property_from_class_like( env @@ -4876,8 +4860,9 @@ impl<'a> TypeChecker<'a> { .unwrap(), property, false, + env, ), - Type::Struct(ref s) => self.get_property_from_class_like(s, property, true), + Type::Struct(ref s) => self.get_property_from_class_like(s, property, true, env), _ => { self .spanned_error_with_var(property, "Property not found".to_string()) @@ -4892,13 +4877,44 @@ impl<'a> TypeChecker<'a> { class: &impl ClassLike, property: &Symbol, allow_static: bool, + env: &SymbolEnv, ) -> VariableInfo { let lookup_res = class.get_env().lookup_ext(property, None); - if let LookupResult::Found(field, _) = lookup_res { + if let LookupResult::Found(field, lookup_info) = lookup_res { let var = field.as_variable().expect("Expected property to be a variable"); - // let SymbolEnvKind::Type(def_type) = lookup_info.env.kind else { // TODO: make an "as_type_env" method - // panic!("Expected env to be a type env"); - // }; + + // Determine the access type of the property + let mut private_access = false; + let mut protected_access = false; + if let Some(current_class) = self.ctx.current_class().map(|udt| udt.clone()) { + let current_class_type = self + .resolve_user_defined_type(¤t_class, env, self.ctx.current_stmt_idx()) + .unwrap(); + // Lookup the property in the class env to find out in which class (perhaps an ancestor) it was defined + let SymbolEnvKind::Type(property_defined_in) = lookup_info.env.kind else { + panic!("Expected env to be a type env"); + }; + private_access = current_class_type.is_same_type_as(&property_defined_in); + protected_access = private_access || current_class_type.is_strict_subtype_of(&property_defined_in); + } + // Compare the access type with what's allowed + match var.access_modifier { + AccessModifier::Private => { + if !private_access { + self.spanned_error(property, format!("Cannot access private member {property} of {class}")); + } + } + AccessModifier::Protected => { + if !protected_access { + self.spanned_error( + property, + format!("Cannot access protected member {property} of {class}"), + ); + } + } + AccessModifier::Public => {} // keep this here to make sure we don't add a new access modifier without handling it here + } + if let VariableKind::StaticMember = var.kind { if allow_static { return var.clone(); @@ -4999,24 +5015,6 @@ impl<'a> TypeChecker<'a> { } } - /// Returns the type in which the property is defined (this might be any class like type). It might - /// be either the passed `instance_type` or one of its ancestors. - fn get_definition_type(&self, instance_type: UnsafeRef, property: &Symbol) -> UnsafeRef { - let class_like_env = match &*instance_type { - Type::Class(c) => &c.env, - Type::Interface(i) => &i.env, - Type::Struct(s) => &s.env, - _ => panic!("Expected instance type to be a class like type"), - }; - let SymbolEnvKind::Type(property_defined_in) = class_like_env - .lookup_ext(property, None) - .expect(&format!("property {property} to be in class {instance_type}")) - .1 - .env.kind else { - panic!("Expected class env to be a type"); - }; - property_defined_in - } } impl VisitorWithContext for TypeChecker<'_> { From 4047b04c714a878c45a10bb907fa1aeff88ed289 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 11:01:54 +0300 Subject: [PATCH 17/56] chuck `pub` in favor of `public` --- libs/tree-sitter-wing/grammar.js | 2 +- .../test/corpus/statements/class_and_resource.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/tree-sitter-wing/grammar.js b/libs/tree-sitter-wing/grammar.js index 563ba74e62d..ac40111642f 100644 --- a/libs/tree-sitter-wing/grammar.js +++ b/libs/tree-sitter-wing/grammar.js @@ -529,7 +529,7 @@ module.exports = grammar({ async_modifier: ($) => "async", - access_modifier: ($) => choice("pub", "protected"), + access_modifier: ($) => choice("public", "protected"), variadic: ($) => "...", diff --git a/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt b/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt index 165ed091e4f..9b98a2ea497 100644 --- a/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt +++ b/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt @@ -74,13 +74,13 @@ class A { inflight init() {} preflight_func() {} async preflight_func() {} - pub preflight_func2() {} + public preflight_func2() {} inflight inflight_func() {} - pub inflight inflight_func2(): num {} + public inflight inflight_func2(): num {} protected inflight inflight_func3(): num {} pf_member: str; inflight if_member: str; - pub inflight var if_member2: str; + public inflight var if_member2: str; protected inflight var if_member3: str; static inflight inflight_field: num; static inflight inflight_method() {} From b3740b0e9e6db8ad2af914fedc007c0ef73827f5 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 11:06:58 +0300 Subject: [PATCH 18/56] updated jsifier tests --- .../base_class_captures_inflight.snap | 2 +- .../base_class_captures_preflight.snap | 2 +- .../snapshots/base_class_lift_indirect.snap | 2 +- .../base_class_with_fields_inflight.snap | 2 +- .../base_class_with_fields_preflight.snap | 2 +- .../base_class_with_lifted_field_object.snap | 2 +- .../base_class_with_lifted_fields.snap | 2 +- ..._static_inflight_from_static_inflight.snap | 2 +- ...from_preflight_scope_with_method_call.snap | 2 +- ...om_preflight_scope_with_nested_object.snap | 2 +- .../snapshots/capture_type_static_method.snap | 2 +- ...ure_type_static_method_inflight_class.snap | 2 +- .../src/jsify/snapshots/closure_field.snap | 2 +- .../src/jsify/snapshots/indirect_capture.snap | 2 +- libs/wingc/src/jsify/snapshots/lift_this.snap | 2 +- .../jsify/snapshots/lift_var_with_this.snap | 2 +- ...ed_inflight_after_preflight_operation.snap | 2 +- .../snapshots/nested_preflight_operation.snap | 4 +- ...eflight_nested_object_with_operations.snap | 2 +- .../src/jsify/snapshots/preflight_object.snap | 4 +- .../preflight_object_through_property.snap | 2 +- .../snapshots/preflight_value_field.snap | 4 +- .../snapshots/reference_inflight_class.snap | 2 +- .../snapshots/reference_static_inflight.snap | 2 +- ...ght_which_references_preflight_object.snap | 2 +- .../static_external_inflight_class.snap | 2 +- .../static_external_preflight_class.snap | 2 +- .../snapshots/static_inflight_operation.snap | 2 +- .../static_local_inflight_class.snap | 2 +- .../jsify/snapshots/transitive_reference.snap | 2 +- ...ansitive_reference_via_inflight_class.snap | 2 +- .../transitive_reference_via_static.snap | 4 +- libs/wingc/src/jsify/tests.rs | 72 +++++++++---------- libs/wingc/src/parser.rs | 2 +- 34 files changed, 73 insertions(+), 73 deletions(-) diff --git a/libs/wingc/src/jsify/snapshots/base_class_captures_inflight.snap b/libs/wingc/src/jsify/snapshots/base_class_captures_inflight.snap index e4cb52a7035..f1e34035fbf 100644 --- a/libs/wingc/src/jsify/snapshots/base_class_captures_inflight.snap +++ b/libs/wingc/src/jsify/snapshots/base_class_captures_inflight.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs let x = "hello"; class Base { - inflight bar() { + protected inflight bar() { log(x); } } diff --git a/libs/wingc/src/jsify/snapshots/base_class_captures_preflight.snap b/libs/wingc/src/jsify/snapshots/base_class_captures_preflight.snap index b10451c2573..5fa25f2f65c 100644 --- a/libs/wingc/src/jsify/snapshots/base_class_captures_preflight.snap +++ b/libs/wingc/src/jsify/snapshots/base_class_captures_preflight.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs let x = "hello"; class Base { - bar() { + protected bar() { log(x); } } diff --git a/libs/wingc/src/jsify/snapshots/base_class_lift_indirect.snap b/libs/wingc/src/jsify/snapshots/base_class_lift_indirect.snap index 1b8f5ea0d87..bb69f7560dd 100644 --- a/libs/wingc/src/jsify/snapshots/base_class_lift_indirect.snap +++ b/libs/wingc/src/jsify/snapshots/base_class_lift_indirect.snap @@ -13,7 +13,7 @@ source: libs/wingc/src/jsify/tests.rs this.b = new cloud.Bucket(); } - inflight put() { + protected inflight put() { this.b.put("hello", "world"); this.b.list(); } diff --git a/libs/wingc/src/jsify/snapshots/base_class_with_fields_inflight.snap b/libs/wingc/src/jsify/snapshots/base_class_with_fields_inflight.snap index ff1a9d66a57..934e3c797ad 100644 --- a/libs/wingc/src/jsify/snapshots/base_class_with_fields_inflight.snap +++ b/libs/wingc/src/jsify/snapshots/base_class_with_fields_inflight.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class Base { - inflight f: str; + protected inflight f: str; inflight init() { this.f = "hello"; } diff --git a/libs/wingc/src/jsify/snapshots/base_class_with_fields_preflight.snap b/libs/wingc/src/jsify/snapshots/base_class_with_fields_preflight.snap index 97329763e41..8cdbce1a9bb 100644 --- a/libs/wingc/src/jsify/snapshots/base_class_with_fields_preflight.snap +++ b/libs/wingc/src/jsify/snapshots/base_class_with_fields_preflight.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class Base { - f: str; + protected f: str; init() { this.f = "hello"; } diff --git a/libs/wingc/src/jsify/snapshots/base_class_with_lifted_field_object.snap b/libs/wingc/src/jsify/snapshots/base_class_with_lifted_field_object.snap index fd2757e8668..c0e85f849fd 100644 --- a/libs/wingc/src/jsify/snapshots/base_class_with_lifted_field_object.snap +++ b/libs/wingc/src/jsify/snapshots/base_class_with_lifted_field_object.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class Base { - b: cloud.Bucket; + protected b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } diff --git a/libs/wingc/src/jsify/snapshots/base_class_with_lifted_fields.snap b/libs/wingc/src/jsify/snapshots/base_class_with_lifted_fields.snap index 4336a445f65..99a0935e579 100644 --- a/libs/wingc/src/jsify/snapshots/base_class_with_lifted_fields.snap +++ b/libs/wingc/src/jsify/snapshots/base_class_with_lifted_fields.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs let x = "hello"; class Base { - f: str; + protected f: str; init() { this.f = x; } diff --git a/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap b/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap index c09e128ac8a..42de6cdd91e 100644 --- a/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap +++ b/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class A { - static inflight foo() { log("hello"); } + public static inflight foo() { log("hello"); } } inflight class B { diff --git a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap index b3c3590d331..1a9e1063b88 100644 --- a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap +++ b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class Foo { - inflight bar() {} + public inflight bar() {} } let f = new Foo(); diff --git a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap index 5b6c73b029c..5994f8bd5db 100644 --- a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap +++ b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class Foo { - b: cloud.Bucket; + public b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } diff --git a/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap b/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap index 5b8ba4ee037..0f53e74ab48 100644 --- a/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap +++ b/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class Foo { - static inflight bars(): str { return "bar"; } + public static inflight bars(): str { return "bar"; } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap b/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap index 8775dcd5873..42125948c51 100644 --- a/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w inflight class Foo { - static bar(): str { return "bar"; } + public static bar(): str { return "bar"; } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/closure_field.snap b/libs/wingc/src/jsify/snapshots/closure_field.snap index f8947d99ed9..fa3c8b252f8 100644 --- a/libs/wingc/src/jsify/snapshots/closure_field.snap +++ b/libs/wingc/src/jsify/snapshots/closure_field.snap @@ -18,7 +18,7 @@ source: libs/wingc/src/jsify/tests.rs }; } - inflight foo(): str { + public inflight foo(): str { return this.closure("anything"); } } diff --git a/libs/wingc/src/jsify/snapshots/indirect_capture.snap b/libs/wingc/src/jsify/snapshots/indirect_capture.snap index 31ddd9efbee..7d477edfeac 100644 --- a/libs/wingc/src/jsify/snapshots/indirect_capture.snap +++ b/libs/wingc/src/jsify/snapshots/indirect_capture.snap @@ -16,7 +16,7 @@ source: libs/wingc/src/jsify/tests.rs b.list(); } - inflight goo() { + public inflight goo() { this.foo(); } } diff --git a/libs/wingc/src/jsify/snapshots/lift_this.snap b/libs/wingc/src/jsify/snapshots/lift_this.snap index 5b4aa12c190..fe65ac5a0a0 100644 --- a/libs/wingc/src/jsify/snapshots/lift_this.snap +++ b/libs/wingc/src/jsify/snapshots/lift_this.snap @@ -13,7 +13,7 @@ source: libs/wingc/src/jsify/tests.rs inflight bar(): num { return this.x; } - inflight foo(): num { + public inflight foo(): num { return this.bar() / 2; } } diff --git a/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap b/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap index 12743983963..e7edfae2a20 100644 --- a/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap +++ b/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class Foo { - value: str; + public value: str; init() { this.value = "hello"; } } diff --git a/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap b/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap index 904051771c1..798f0bb5337 100644 --- a/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap +++ b/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap @@ -7,7 +7,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class YourType { - inflight b: str; + public inflight b: str; inflight init() { this.b = "hello"; } diff --git a/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap b/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap index e0abb54aadb..798cbb73b64 100644 --- a/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap +++ b/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap @@ -7,13 +7,13 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class YourType { - b: cloud.Bucket; + public b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } } class MyType { - y: YourType; + public y: YourType; init() { this.y = new YourType(); } diff --git a/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap b/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap index 0076165bd22..88478244483 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; let b = new cloud.Bucket(); class A { - bucky: cloud.Bucket; + public bucky: cloud.Bucket; init() { this.bucky = b; } diff --git a/libs/wingc/src/jsify/snapshots/preflight_object.snap b/libs/wingc/src/jsify/snapshots/preflight_object.snap index 61f69324a93..4ae47e7c53e 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_object.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_object.snap @@ -6,8 +6,8 @@ source: libs/wingc/src/jsify/tests.rs ```w class A { - inflight hello() {} - inflight goodbye() {} + public inflight hello() {} + public inflight goodbye() {} } let pf_obj = new A(); test "test" { diff --git a/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap b/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap index 69d44c46470..df0bff878e0 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class MyType { - b: cloud.Bucket; + public b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } diff --git a/libs/wingc/src/jsify/snapshots/preflight_value_field.snap b/libs/wingc/src/jsify/snapshots/preflight_value_field.snap index 024c05c5c9d..9aa911dacd8 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_value_field.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_value_field.snap @@ -6,8 +6,8 @@ source: libs/wingc/src/jsify/tests.rs ```w class MyType { - name: str; - last: str; + public name: str; + public last: str; init() { this.name = "hello"; diff --git a/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap b/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap index ca2b24327fb..704ea18ff21 100644 --- a/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w inflight class Foo { - static a(): str { return "a"; } + public static a(): str { return "a"; } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap b/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap index 7ca285246ec..802cc769b21 100644 --- a/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap +++ b/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class MyType { - static inflight myStaticMethod(): str {} + public static inflight myStaticMethod(): str {} } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap b/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap index ac4fd7c3bef..12994c71f20 100644 --- a/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap +++ b/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap @@ -10,7 +10,7 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); class MyType { - static inflight staticMethod(): str { + public static inflight staticMethod(): str { b.list(); return "foo"; } diff --git a/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap b/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap index 7bbc0b52b86..be03f914efa 100644 --- a/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w inflight class A { - static foo() { log("hello"); } + public static foo() { log("hello"); } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap b/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap index 6ead7cfac7a..4af4b0f4ba3 100644 --- a/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class A { - static inflight foo() { log("hello"); } + public static inflight foo() { log("hello"); } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap b/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap index a1f195aeac1..6c196395573 100644 --- a/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap +++ b/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap @@ -9,7 +9,7 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); class A { - static inflight myop() { + public static inflight myop() { b.list(); } } diff --git a/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap b/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap index d2a2ff479a5..fc7702388c6 100644 --- a/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap @@ -7,7 +7,7 @@ source: libs/wingc/src/jsify/tests.rs test "test" { class A { - static foo() { log("hello"); } + public static foo() { log("hello"); } } class B { diff --git a/libs/wingc/src/jsify/snapshots/transitive_reference.snap b/libs/wingc/src/jsify/snapshots/transitive_reference.snap index bbd93d73e5b..e87682f7b45 100644 --- a/libs/wingc/src/jsify/snapshots/transitive_reference.snap +++ b/libs/wingc/src/jsify/snapshots/transitive_reference.snap @@ -18,7 +18,7 @@ source: libs/wingc/src/jsify/tests.rs return this.b.list().length == 0; } - inflight checkIfEmpty() { + public inflight checkIfEmpty() { if this.isEmpty() { log("empty!"); } diff --git a/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap b/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap index e01e02afe4c..e5804c45e79 100644 --- a/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap @@ -10,7 +10,7 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); inflight class MyInflightClass { - putInBucket() { + public putInBucket() { b.put("in", "bucket"); } } diff --git a/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap b/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap index 50ac0947cc5..e751a8a0e9e 100644 --- a/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap +++ b/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap @@ -10,13 +10,13 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); class MyType { - static inflight putInBucket() { + public static inflight putInBucket() { b.put("in", "bucket"); } } class YourType { - inflight putIndirect() { + public inflight putIndirect() { MyType.putInBucket(); } } diff --git a/libs/wingc/src/jsify/tests.rs b/libs/wingc/src/jsify/tests.rs index bd496b91158..8bfe0c2f927 100644 --- a/libs/wingc/src/jsify/tests.rs +++ b/libs/wingc/src/jsify/tests.rs @@ -48,7 +48,7 @@ fn call_static_inflight_from_static_inflight() { assert_compile_ok!( r#" class A { - static inflight foo() { log("hello"); } + public static inflight foo() { log("hello"); } } inflight class B { @@ -66,7 +66,7 @@ fn static_local_inflight_class() { r#" test "test" { class A { - static foo() { log("hello"); } + public static foo() { log("hello"); } } class B { @@ -86,7 +86,7 @@ fn static_external_inflight_class() { assert_compile_ok!( r#" inflight class A { - static foo() { log("hello"); } + public static foo() { log("hello"); } } test "test" { @@ -106,7 +106,7 @@ fn static_external_preflight_class() { assert_compile_ok!( r#" class A { - static inflight foo() { log("hello"); } + public static inflight foo() { log("hello"); } } test "test" { @@ -177,8 +177,8 @@ fn preflight_object() { assert_compile_ok!( r#" class A { - inflight hello() {} - inflight goodbye() {} + public inflight hello() {} + public inflight goodbye() {} } let pf_obj = new A(); test "test" { @@ -247,7 +247,7 @@ fn preflight_nested_object_with_operations() { bring cloud; let b = new cloud.Bucket(); class A { - bucky: cloud.Bucket; + public bucky: cloud.Bucket; init() { this.bucky = b; } @@ -269,7 +269,7 @@ fn static_inflight_operation() { let b = new cloud.Bucket(); class A { - static inflight myop() { + public static inflight myop() { b.list(); } } @@ -399,7 +399,7 @@ fn capture_type_static_method() { assert_compile_ok!( r#" class Foo { - static inflight bars(): str { return "bar"; } + public static inflight bars(): str { return "bar"; } } test "test" { @@ -414,7 +414,7 @@ fn capture_type_static_method_inflight_class() { assert_compile_ok!( r#" inflight class Foo { - static bar(): str { return "bar"; } + public static bar(): str { return "bar"; } } test "test" { @@ -545,7 +545,7 @@ fn capture_identifier_from_preflight_scope_with_method_call() { assert_compile_ok!( r#" class Foo { - inflight bar() {} + public inflight bar() {} } let f = new Foo(); @@ -563,7 +563,7 @@ fn capture_identifier_from_preflight_scope_with_nested_object() { bring cloud; class Foo { - b: cloud.Bucket; + public b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } @@ -692,8 +692,8 @@ fn preflight_value_field() { assert_compile_ok!( r#" class MyType { - name: str; - last: str; + public name: str; + public last: str; init() { this.name = "hello"; @@ -735,13 +735,13 @@ fn nested_preflight_operation() { r#" bring cloud; class YourType { - b: cloud.Bucket; + public b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } } class MyType { - y: YourType; + public y: YourType; init() { this.y = new YourType(); } @@ -762,7 +762,7 @@ fn nested_inflight_after_preflight_operation() { r#" bring cloud; class YourType { - inflight b: str; + public inflight b: str; inflight init() { this.b = "hello"; } @@ -802,7 +802,7 @@ fn preflight_object_through_property() { bring cloud; class MyType { - b: cloud.Bucket; + public b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } @@ -837,7 +837,7 @@ fn reference_static_inflight() { assert_compile_ok!( r#" class MyType { - static inflight myStaticMethod(): str {} + public static inflight myStaticMethod(): str {} } test "test" { @@ -858,7 +858,7 @@ fn reference_static_inflight_which_references_preflight_object() { let b = new cloud.Bucket(); class MyType { - static inflight staticMethod(): str { + public static inflight staticMethod(): str { b.list(); return "foo"; } @@ -962,7 +962,7 @@ fn transitive_reference() { return this.b.list().length == 0; } - inflight checkIfEmpty() { + public inflight checkIfEmpty() { if this.isEmpty() { log("empty!"); } @@ -1012,13 +1012,13 @@ fn transitive_reference_via_static() { let b = new cloud.Bucket(); class MyType { - static inflight putInBucket() { + public static inflight putInBucket() { b.put("in", "bucket"); } } class YourType { - inflight putIndirect() { + public inflight putIndirect() { MyType.putInBucket(); } } @@ -1053,7 +1053,7 @@ fn transitive_reference_via_inflight_class() { let b = new cloud.Bucket(); inflight class MyInflightClass { - putInBucket() { + public putInBucket() { b.put("in", "bucket"); } } @@ -1071,7 +1071,7 @@ fn reference_inflight_class() { assert_compile_ok!( r#" inflight class Foo { - static a(): str { return "a"; } + public static a(): str { return "a"; } } test "test" { @@ -1476,7 +1476,7 @@ fn base_class_captures_preflight() { let x = "hello"; class Base { - bar() { + protected bar() { log(x); } } @@ -1497,7 +1497,7 @@ fn base_class_captures_inflight() { let x = "hello"; class Base { - inflight bar() { + protected inflight bar() { log(x); } } @@ -1516,7 +1516,7 @@ fn base_class_with_fields_preflight() { assert_compile_ok!( r#" class Base { - f: str; + protected f: str; init() { this.f = "hello"; } @@ -1542,7 +1542,7 @@ fn base_class_with_fields_inflight() { assert_compile_ok!( r#" class Base { - inflight f: str; + protected inflight f: str; inflight init() { this.f = "hello"; } @@ -1570,7 +1570,7 @@ fn base_class_with_lifted_fields() { let x = "hello"; class Base { - f: str; + protected f: str; init() { this.f = x; } @@ -1615,7 +1615,7 @@ fn base_class_with_lifted_field_object() { bring cloud; class Base { - b: cloud.Bucket; + protected b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } @@ -1642,7 +1642,7 @@ fn base_class_lift_indirect() { this.b = new cloud.Bucket(); } - inflight put() { + protected inflight put() { this.b.put("hello", "world"); this.b.list(); } @@ -1691,7 +1691,7 @@ fn indirect_capture() { b.list(); } - inflight goo() { + public inflight goo() { this.foo(); } } @@ -1746,7 +1746,7 @@ fn lift_this() { inflight bar(): num { return this.x; } - inflight foo(): num { + public inflight foo(): num { return this.bar() / 2; } } @@ -1859,7 +1859,7 @@ fn closure_field() { }; } - inflight foo(): str { + public inflight foo(): str { return this.closure("anything"); } } @@ -1910,7 +1910,7 @@ fn lift_var_with_this() { assert_compile_ok!( r#" class Foo { - value: str; + public value: str; init() { this.value = "hello"; } } diff --git a/libs/wingc/src/parser.rs b/libs/wingc/src/parser.rs index 5c829103f84..6b612a004ce 100644 --- a/libs/wingc/src/parser.rs +++ b/libs/wingc/src/parser.rs @@ -1281,7 +1281,7 @@ impl<'s> Parser<'s> { fn build_access_modifier(&self, am_node: Option) -> DiagnosticResult { match am_node { Some(am_node) => match self.node_text(&am_node) { - "pub" => Ok(AccessModifier::Public), + "public" => Ok(AccessModifier::Public), "protected" => Ok(AccessModifier::Protected), other => self.with_error(format!("Unknown access modifier {other}"), &am_node), }, From aefdf4d6c6732cc9a14c3fd1c687e72b243c8936 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 13:21:28 +0300 Subject: [PATCH 19/56] handle inner classes --- examples/tests/invalid/access_modifiers.w | 18 +++++++++++++++--- libs/wingc/src/type_check.rs | 16 ++++++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/examples/tests/invalid/access_modifiers.w b/examples/tests/invalid/access_modifiers.w index 0baa4830a67..fab42416139 100644 --- a/examples/tests/invalid/access_modifiers.w +++ b/examples/tests/invalid/access_modifiers.w @@ -1,7 +1,7 @@ class Foo { protected protected_field: str; private_field: str; - pub public_field: str; + public public_field: str; init() { this.protected_field = "hello"; @@ -17,13 +17,22 @@ class Foo { this.public_method(); this.protected_method(); this.private_method(); + + class InnerFoo { + method(f: Foo) { + // Check access from inner class + log(f.protected_field); + log(f.private_field); + log(f.public_field); + } + } } - pub public_method() {} + public public_method() {} protected protected_method() {} private_method() {} - pub static public_static_method() {} + public static public_static_method() {} protected static protected_static_method() {} static private_static_method() {} } @@ -86,3 +95,6 @@ class BarBar { // ^ Cannot access private member } } + +// TODO: check jsii imported access modifiers + diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 318236f8c8e..9c1f60c360b 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -4884,19 +4884,24 @@ impl<'a> TypeChecker<'a> { let var = field.as_variable().expect("Expected property to be a variable"); // Determine the access type of the property + // Lookup the property in the class env to find out in which class (perhaps an ancestor) it was defined + let SymbolEnvKind::Type(property_defined_in) = lookup_info.env.kind else { + panic!("Expected env to be a type env"); + }; + // Check if the class in which the property is defined is the current class nesting let mut private_access = false; let mut protected_access = false; - if let Some(current_class) = self.ctx.current_class().map(|udt| udt.clone()) { + for current_class in self.ctx.current_class_nesting() { let current_class_type = self .resolve_user_defined_type(¤t_class, env, self.ctx.current_stmt_idx()) .unwrap(); - // Lookup the property in the class env to find out in which class (perhaps an ancestor) it was defined - let SymbolEnvKind::Type(property_defined_in) = lookup_info.env.kind else { - panic!("Expected env to be a type env"); - }; private_access = current_class_type.is_same_type_as(&property_defined_in); protected_access = private_access || current_class_type.is_strict_subtype_of(&property_defined_in); + if private_access { + break; + } } + // Compare the access type with what's allowed match var.access_modifier { AccessModifier::Private => { @@ -5014,7 +5019,6 @@ impl<'a> TypeChecker<'a> { (None, None) } } - } impl VisitorWithContext for TypeChecker<'_> { From 443ad8d3e2eba013f9b2d9ea63afccc992b2ef1a Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 13:21:53 +0300 Subject: [PATCH 20/56] inner classes --- libs/wingc/src/visit_context.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/wingc/src/visit_context.rs b/libs/wingc/src/visit_context.rs index 5284a68cf94..2c36ed3ae96 100644 --- a/libs/wingc/src/visit_context.rs +++ b/libs/wingc/src/visit_context.rs @@ -1,3 +1,5 @@ +use itertools::Itertools; + use crate::{ ast::{ExprId, FunctionSignature, Phase, Symbol, UserDefinedType}, type_check::symbol_env::SymbolEnvRef, @@ -91,6 +93,10 @@ impl VisitContext { self.class.last() } + pub fn current_class_nesting(&self) -> Vec { + self.class.iter().rev().map(|udt| udt.clone()).collect_vec() + } + // -- pub fn push_function_definition( From d99a36fe1733d43602b6d57fd163f53d3174588d Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 14:07:52 +0300 Subject: [PATCH 21/56] wip --- examples/tests/invalid/access_modifiers.w | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/tests/invalid/access_modifiers.w b/examples/tests/invalid/access_modifiers.w index fab42416139..5e8712985ae 100644 --- a/examples/tests/invalid/access_modifiers.w +++ b/examples/tests/invalid/access_modifiers.w @@ -97,4 +97,4 @@ class BarBar { } // TODO: check jsii imported access modifiers - +// TODO: add tests and implement checks for overriding methods with different access modifiers From c5e7de7b81bae4d1671c306522125c9c7dadf16b Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 14:08:57 +0300 Subject: [PATCH 22/56] fixed tests (added `public`) --- examples/tests/valid/baz.w | 2 +- examples/tests/valid/call_static_of_myself.w | 10 +++--- .../tests/valid/calling_inflight_variants.w | 4 +-- .../valid/capture_reassigable_class_field.w | 6 ++-- .../valid/capture_resource_with_no_inflight.w | 4 +-- examples/tests/valid/capture_tokens.w | 4 +-- examples/tests/valid/class.w | 22 ++++++------- examples/tests/valid/closure_class.w | 2 +- examples/tests/valid/double_reference.w | 6 ++-- examples/tests/valid/doubler.w | 2 +- examples/tests/valid/dynamo.w | 2 +- examples/tests/valid/dynamo_awscdk.w | 4 +-- examples/tests/valid/extern_implementation.w | 8 ++--- .../tests/valid/inflight_capture_static.w | 6 ++-- .../valid/inflight_class_as_struct_members.w | 2 +- .../valid/inflight_class_capture_const.w | 2 +- .../tests/valid/inflight_class_definitions.w | 16 +++++----- .../inflight_class_inner_capture_mutable.w | 2 +- .../inflight_class_inside_inflight_closure.w | 6 ++-- .../inflight_class_outside_inflight_closure.w | 2 +- .../tests/valid/inflights_calling_inflights.w | 2 +- examples/tests/valid/json.w | 2 +- examples/tests/valid/lift_expr_with_this.w | 2 +- examples/tests/valid/lift_this.w | 2 +- examples/tests/valid/lift_via_closure.w | 4 +-- examples/tests/valid/nil.w | 6 ++-- examples/tests/valid/optionals.w | 8 ++--- examples/tests/valid/reassignment.w | 4 +-- examples/tests/valid/resource.w | 18 +++++------ examples/tests/valid/resource_call_static.w | 2 +- examples/tests/valid/resource_captures.w | 32 +++++++++---------- .../tests/valid/resource_captures_globals.w | 12 +++---- examples/tests/valid/static_members.w | 8 ++--- examples/tests/valid/store.w | 2 +- examples/tests/valid/subdir/bar.w | 2 +- examples/tests/valid/subdir/foo.w | 6 ++-- examples/tests/valid/super_call.w | 6 ++-- ..._with_lifted_field_object_unqualified.snap | 1 + .../snapshots/fails_on_preflight_static.snap | 1 + 39 files changed, 117 insertions(+), 115 deletions(-) diff --git a/examples/tests/valid/baz.w b/examples/tests/valid/baz.w index 3fd35230b61..1d250d59ac9 100644 --- a/examples/tests/valid/baz.w +++ b/examples/tests/valid/baz.w @@ -1,7 +1,7 @@ // used by bring_local_normalization.w class Baz { - static baz(): str { + public static baz(): str { return "baz"; } } diff --git a/examples/tests/valid/call_static_of_myself.w b/examples/tests/valid/call_static_of_myself.w index 0c94eafae31..a38c2b03bd5 100644 --- a/examples/tests/valid/call_static_of_myself.w +++ b/examples/tests/valid/call_static_of_myself.w @@ -1,17 +1,17 @@ class Foo { - static inflight foo(): num { return 1; } + public static inflight foo(): num { return 1; } static inflight bar(): num { return Foo.foo(); } - inflight callThis(): num { + public inflight callThis(): num { return Foo.bar(); } } inflight class Bar { - static bar(): num { return 2; } + public static bar(): num { return 2; } - callThis(): num { + public callThis(): num { return Bar.bar(); } } @@ -20,7 +20,7 @@ let foo = new Foo(); test "test" { class Zoo { - static zoo(): num { return 3; } + public static zoo(): num { return 3; } } let bar = new Bar(); diff --git a/examples/tests/valid/calling_inflight_variants.w b/examples/tests/valid/calling_inflight_variants.w index fa2bbf1c3f3..30c601cebda 100644 --- a/examples/tests/valid/calling_inflight_variants.w +++ b/examples/tests/valid/calling_inflight_variants.w @@ -27,14 +27,14 @@ class Foo { } } - inflight callFn(x: bool): num { + public inflight callFn(x: bool): num { // partialFn could be an inflight function created during preflight or inflight, // so we have to code-generate this to work for both cases let partialFn = this.makeFn(x); return partialFn(); } - inflight callFn2(): void { + public inflight callFn2(): void { // now we call inflight1 and inflight2 directly which know they are handler classes let one = this.inflight1(); let two = this.inflight2(); diff --git a/examples/tests/valid/capture_reassigable_class_field.w b/examples/tests/valid/capture_reassigable_class_field.w index f81ad31889c..31f793ca835 100644 --- a/examples/tests/valid/capture_reassigable_class_field.w +++ b/examples/tests/valid/capture_reassigable_class_field.w @@ -9,15 +9,15 @@ class KeyValueStore { this.onUpdateCallback = inflight (k: str) => {}; } - onUpdate(fn: inflight (str):void){ + public onUpdate(fn: inflight (str):void){ this.onUpdateCallback = fn; } - inflight get(key: str): Json { + public inflight get(key: str): Json { this.onUpdateCallback(key); return this.bucket.getJson(key); } - inflight set(key: str, value: Json): void { + public inflight set(key: str, value: Json): void { this.bucket.putJson(key, value); } } diff --git a/examples/tests/valid/capture_resource_with_no_inflight.w b/examples/tests/valid/capture_resource_with_no_inflight.w index d85b463b1ab..3fdac921141 100644 --- a/examples/tests/valid/capture_resource_with_no_inflight.w +++ b/examples/tests/valid/capture_resource_with_no_inflight.w @@ -1,7 +1,7 @@ bring cloud; class A { - field: str; + public field: str; counter: cloud.Counter; init() { @@ -13,7 +13,7 @@ class A { this.counter.inc(); } - inflight bar() { } + public inflight bar() { } } let a = new A(); diff --git a/examples/tests/valid/capture_tokens.w b/examples/tests/valid/capture_tokens.w index de533ff6e99..f5bdc26db5f 100644 --- a/examples/tests/valid/capture_tokens.w +++ b/examples/tests/valid/capture_tokens.w @@ -4,14 +4,14 @@ class MyResource { api: cloud.Api; url: str; - extern "./url_utils.js" static inflight isValidUrl(url: str): bool; + extern "./url_utils.js" public static inflight isValidUrl(url: str): bool; init() { this.api = new cloud.Api(); this.url = this.api.url; } - inflight foo() { + public inflight foo() { assert(MyResource.isValidUrl(this.url)); assert(MyResource.isValidUrl(this.api.url)); } diff --git a/examples/tests/valid/class.w b/examples/tests/valid/class.w index ecb6c6526e2..b8c246d90c9 100644 --- a/examples/tests/valid/class.w +++ b/examples/tests/valid/class.w @@ -6,7 +6,7 @@ new C1(); // class with init and no arguments class C2 { - x: num; + public x: num; init() { this.x = 1; } @@ -16,8 +16,8 @@ assert(c2.x == 1); // class with init and arguments class C3 { - x: num; - y: num; + public x: num; + public y: num; init(a: num, b: num) { this.x = a; if true { @@ -31,19 +31,19 @@ assert(c3.y == 2); // class with static method and no init class C4 { - static m():num {return 1;} + public static m():num {return 1;} } assert(C4.m() == 1); // class with inflight field class C5 { - inflight x: num; - inflight var y: num; + public inflight x: num; + public inflight var y: num; inflight init() { this.x = 123; this.y = 321; } - inflight set(b: num) { + public inflight set(b: num) { this.y = b; } } @@ -57,14 +57,14 @@ test "access inflight field" { } class Person { - name: str; + public name: str; init(name: str) { this.name = name; } } class Student extends Person { - major: str; + public major: str; init(name: str, major: str) { super(name); @@ -73,7 +73,7 @@ class Student extends Person { } class PaidStudent extends Student { - hrlyWage: num; + public hrlyWage: num; init(name: str, major: str, hrlyWage: num) { super(name, major); this.hrlyWage = hrlyWage; @@ -103,7 +103,7 @@ test "devived class init body happens after super" { // Inflight inheritence inflight class A { - sound: str; + public sound: str; inflight init(sound: str) { this.sound = sound; diff --git a/examples/tests/valid/closure_class.w b/examples/tests/valid/closure_class.w index 71877cba7ac..373fb2f326c 100644 --- a/examples/tests/valid/closure_class.w +++ b/examples/tests/valid/closure_class.w @@ -1,5 +1,5 @@ class MyClosure { - inflight another(): str { + public inflight another(): str { return "hello"; } diff --git a/examples/tests/valid/double_reference.w b/examples/tests/valid/double_reference.w index dabd9849157..4a943d5b94d 100644 --- a/examples/tests/valid/double_reference.w +++ b/examples/tests/valid/double_reference.w @@ -7,16 +7,16 @@ class Foo { initCount.inc(); } - inflight method() { } + public inflight method() { } } class Bar { - foo: Foo; + public foo: Foo; init() { this.foo = new Foo(); } - inflight callFoo() { + public inflight callFoo() { this.foo.method(); } } diff --git a/examples/tests/valid/doubler.w b/examples/tests/valid/doubler.w index bde9b2045e0..231e95bc9b1 100644 --- a/examples/tests/valid/doubler.w +++ b/examples/tests/valid/doubler.w @@ -23,7 +23,7 @@ let fn = new Doubler(inflight (m: str): str => { class Doubler2 { // TODO: make into a static method - see https://github.com/winglang/wing/issues/2583 - makeFunc(handler: inflight (num): num): cloud.Function { + public makeFunc(handler: inflight (num): num): cloud.Function { return new cloud.Function(inflight (x: str): str => { let xStr = num.fromStr(x); let y = handler(xStr); diff --git a/examples/tests/valid/dynamo.w b/examples/tests/valid/dynamo.w index e235cf44c06..06b3f606fa9 100644 --- a/examples/tests/valid/dynamo.w +++ b/examples/tests/valid/dynamo.w @@ -56,7 +56,7 @@ class DynamoTable { extern "./dynamo.js" static inflight _putItem(tableName: str, item: Json): void; - inflight putItem(item: Map) { + public inflight putItem(item: Map) { let json = this._itemToJson(item); DynamoTable._putItem(this.tableName, json); } diff --git a/examples/tests/valid/dynamo_awscdk.w b/examples/tests/valid/dynamo_awscdk.w index 8c5f2c92959..c472e59a187 100644 --- a/examples/tests/valid/dynamo_awscdk.w +++ b/examples/tests/valid/dynamo_awscdk.w @@ -61,13 +61,13 @@ class DynamoTable { } extern "./dynamo.js" static inflight _putItem(tableName: str, item: Json): void; - inflight putItem(item: Map) { + public inflight putItem(item: Map) { let json = this._itemToJson(item); DynamoTable._putItem(this.tableName, json); } extern "./dynamo.js" static inflight _getItem(tableName: str, key: Json): Json; - inflight getItem(key: Map): Json { + public inflight getItem(key: Map): Json { let json = this._itemToJson(key); return DynamoTable._getItem(this.tableName, json); } diff --git a/examples/tests/valid/extern_implementation.w b/examples/tests/valid/extern_implementation.w index b5fac4684dd..c51019446d2 100644 --- a/examples/tests/valid/extern_implementation.w +++ b/examples/tests/valid/extern_implementation.w @@ -1,14 +1,14 @@ bring cloud; class Foo { - extern "./external_js.js" static getGreeting(name: str): str; + extern "./external_js.js" public static getGreeting(name: str): str; extern "./external_js.js" static inflight regexInflight(pattern: str, text: str): bool; extern "./external_js.js" static inflight getUuid(): str; extern "./external_js.js" static inflight getData(): str; - extern "./external_js.js" static inflight print(msg: str); - extern "uuid" static v4(): str; + extern "./external_js.js" public static inflight print(msg: str); + extern "uuid" public static v4(): str; - inflight call() { + public inflight call() { assert(Foo.regexInflight("[a-z]+-\\d+", "abc-123")); let uuid = Foo.getUuid(); assert(uuid.length == 36); diff --git a/examples/tests/valid/inflight_capture_static.w b/examples/tests/valid/inflight_capture_static.w index 6af093db724..8220f9a7856 100644 --- a/examples/tests/valid/inflight_capture_static.w +++ b/examples/tests/valid/inflight_capture_static.w @@ -1,13 +1,13 @@ bring util; class Preflight { - static inflight staticMethod(a: num): str { + public static inflight staticMethod(a: num): str { return "foo-${a}"; } } inflight class OuterInflight { - static staticMethod(b: str): num { + public static staticMethod(b: str): num { return b.length; } } @@ -22,7 +22,7 @@ test "call static method of an outer inflight class" { test "call static method of an inner inflight class" { class InnerInflight { - static staticMethod(): str { return "hello"; } + public static staticMethod(): str { return "hello"; } } assert(InnerInflight.staticMethod() == "hello"); diff --git a/examples/tests/valid/inflight_class_as_struct_members.w b/examples/tests/valid/inflight_class_as_struct_members.w index 7893a91eb7e..0d2f06d67e1 100644 --- a/examples/tests/valid/inflight_class_as_struct_members.w +++ b/examples/tests/valid/inflight_class_as_struct_members.w @@ -1,5 +1,5 @@ inflight class Foo { - get(): num { return 42; } + public get(): num { return 42; } } struct Bar { diff --git a/examples/tests/valid/inflight_class_capture_const.w b/examples/tests/valid/inflight_class_capture_const.w index 2805c2a9cc9..3e48bcdcbc9 100644 --- a/examples/tests/valid/inflight_class_capture_const.w +++ b/examples/tests/valid/inflight_class_capture_const.w @@ -3,7 +3,7 @@ bring cloud; let myConst = "bang bang"; inflight class Foo { - getValue(): str { + public getValue(): str { return myConst; } } diff --git a/examples/tests/valid/inflight_class_definitions.w b/examples/tests/valid/inflight_class_definitions.w index 620a004cf52..8cbb986b2b9 100644 --- a/examples/tests/valid/inflight_class_definitions.w +++ b/examples/tests/valid/inflight_class_definitions.w @@ -1,18 +1,18 @@ class A { - foo(): str { return "a1"; } - inflight goo(): str { return "a2"; } + public foo(): str { return "a1"; } + public inflight goo(): str { return "a2"; } } let a = new A(); assert(a.foo() == "a1"); inflight class B { - foo(): str { return "b1"; } + public foo(): str { return "b1"; } } let fn = inflight () => { inflight class C { - foo(): str { return "c1"; } + public foo(): str { return "c1"; } } let c = new C(); @@ -24,14 +24,14 @@ class D { init() { class E { - foo(): str { return "e1"; } + public foo(): str { return "e1"; } } let pb = new E(); assert(pb.foo() == "e1"); inflight class F { - foo(): str { return "f1"; } + public foo(): str { return "f1"; } } this.inner = inflight (): str => { @@ -39,11 +39,11 @@ class D { }; } - getInner(): inflight (): str { + public getInner(): inflight (): str { return this.inner; } - inflight callInner(): str { + public inflight callInner(): str { return this.inner(); } } diff --git a/examples/tests/valid/inflight_class_inner_capture_mutable.w b/examples/tests/valid/inflight_class_inner_capture_mutable.w index 435d97b7a40..d6106a6d7b9 100644 --- a/examples/tests/valid/inflight_class_inner_capture_mutable.w +++ b/examples/tests/valid/inflight_class_inner_capture_mutable.w @@ -5,7 +5,7 @@ test "inner inflight class capture immutable" { let var i = 10; class Inner { - dang(): num { + public dang(): num { y.push(2); // since the inner class is defined within the same scope, it is actually possible to reassign diff --git a/examples/tests/valid/inflight_class_inside_inflight_closure.w b/examples/tests/valid/inflight_class_inside_inflight_closure.w index 6eb51931381..8242d1b92e0 100644 --- a/examples/tests/valid/inflight_class_inside_inflight_closure.w +++ b/examples/tests/valid/inflight_class_inside_inflight_closure.w @@ -5,7 +5,7 @@ class PreflightClass { init() { this.b = new cloud.Bucket(); } - preflight_method(): cloud.Function { + public preflight_method(): cloud.Function { let inflight_closure = inflight (payload: str) => { this.b.put("k","v"); // Here `this` is the parent class instance inflight class InflightClass { @@ -13,7 +13,7 @@ class PreflightClass { init() { this.field = "value"; } - inflight method() { + public inflight method() { assert(this.field == "value"); // Here `this` is the inflight class instance } } @@ -34,7 +34,7 @@ test "it works" { test "inflight class inside closure captures from closure" { let x = 12; class Foo { - getX(): num { return x; } + public getX(): num { return x; } } let foo = new Foo(); diff --git a/examples/tests/valid/inflight_class_outside_inflight_closure.w b/examples/tests/valid/inflight_class_outside_inflight_closure.w index 7e91940e625..42904a64f37 100644 --- a/examples/tests/valid/inflight_class_outside_inflight_closure.w +++ b/examples/tests/valid/inflight_class_outside_inflight_closure.w @@ -9,7 +9,7 @@ inflight class BinaryOperation { this.rhs = rhs; } - add(): num { + public add(): num { return this.lhs + this.rhs; } } diff --git a/examples/tests/valid/inflights_calling_inflights.w b/examples/tests/valid/inflights_calling_inflights.w index 5f1d64e27b7..03f8203c94c 100644 --- a/examples/tests/valid/inflights_calling_inflights.w +++ b/examples/tests/valid/inflights_calling_inflights.w @@ -29,7 +29,7 @@ class MyResource { }; } - inflight foo(): str { + public inflight foo(): str { return this.closure("anything"); } } diff --git a/examples/tests/valid/json.w b/examples/tests/valid/json.w index 8d9d2de4558..4f9c2a215a0 100644 --- a/examples/tests/valid/json.w +++ b/examples/tests/valid/json.w @@ -35,7 +35,7 @@ let jj3 = Json getStr(); assert(jj3 == Json "hello"); class Foo { - SumStr: str; + public SumStr: str; init() { this.SumStr = "wow!"; } diff --git a/examples/tests/valid/lift_expr_with_this.w b/examples/tests/valid/lift_expr_with_this.w index f660bbe8e77..37ca20428ad 100644 --- a/examples/tests/valid/lift_expr_with_this.w +++ b/examples/tests/valid/lift_expr_with_this.w @@ -1,5 +1,5 @@ class Foo { - value: str; + public value: str; init() { this.value = "hello"; } } diff --git a/examples/tests/valid/lift_this.w b/examples/tests/valid/lift_this.w index bb521ca58b0..2462c9b7f31 100644 --- a/examples/tests/valid/lift_this.w +++ b/examples/tests/valid/lift_this.w @@ -6,7 +6,7 @@ class Foo { inflight bar(): num { return this.x; } - inflight foo(): num { + public inflight foo(): num { return this.bar() / 2; } } diff --git a/examples/tests/valid/lift_via_closure.w b/examples/tests/valid/lift_via_closure.w index bcac2a57d52..9729784bbeb 100644 --- a/examples/tests/valid/lift_via_closure.w +++ b/examples/tests/valid/lift_via_closure.w @@ -7,7 +7,7 @@ let fn = inflight () => { }; class MyClosure { - bucket: cloud.Bucket; + public bucket: cloud.Bucket; init() { this.bucket = new cloud.Bucket(); @@ -23,7 +23,7 @@ class MyClosure { this.bucket.put("hello", "world"); } - inflight listFiles(): Array { + public inflight listFiles(): Array { bucket2.put("b2", "world"); return this.bucket.list(); } diff --git a/examples/tests/valid/nil.w b/examples/tests/valid/nil.w index 8490ab94382..35d9b8629e5 100644 --- a/examples/tests/valid/nil.w +++ b/examples/tests/valid/nil.w @@ -7,18 +7,18 @@ class Foo { this.optionalVar = nil; } - inflight returnNil(t: bool): str? { + public inflight returnNil(t: bool): str? { if t { return "hello"; } return nil; } - inflight setOptionalValue(msg: str?) { + public inflight setOptionalValue(msg: str?) { this.optionalVar = msg; } - inflight getOptionalValue(): str? { + public inflight getOptionalValue(): str? { return this.optionalVar; } } diff --git a/examples/tests/valid/optionals.w b/examples/tests/valid/optionals.w index 4833e18a16a..a655d1762a9 100644 --- a/examples/tests/valid/optionals.w +++ b/examples/tests/valid/optionals.w @@ -10,7 +10,7 @@ let y: num = x ?? 5; assert(y == 4); class Super { - name: str; + public name: str; init() { this.name = "Super"; } } class Sub extends Super { @@ -136,9 +136,9 @@ assert(fun("hello") == "hello"); assert(fun(nil) == "default"); class Node { - value: num; - left: Node?; - right: Node?; + public value: num; + public left: Node?; + public right: Node?; init(value: num, left: Node?, right: Node?) { this.value = value; diff --git a/examples/tests/valid/reassignment.w b/examples/tests/valid/reassignment.w index 4ad8c0fa94d..f83f2f1e307 100644 --- a/examples/tests/valid/reassignment.w +++ b/examples/tests/valid/reassignment.w @@ -5,7 +5,7 @@ x = x + 1; assert(x == 6); class R { - var f: num; + public var f: num; f1: num; init() { // Initialize fields in `init` but in an inner scope to make sure @@ -16,7 +16,7 @@ class R { } } - inc() { + public inc() { this.f = this.f + 1; } } diff --git a/examples/tests/valid/resource.w b/examples/tests/valid/resource.w index 811c3ead4a8..e0f14643b47 100644 --- a/examples/tests/valid/resource.w +++ b/examples/tests/valid/resource.w @@ -3,7 +3,7 @@ bring cloud; // User defined resource class Foo { c: cloud.Counter; // Use SDK built in resource in the user defined resource - inflight inflightField: num; + public inflight inflightField: num; init() { this.c = new cloud.Counter(); @@ -19,16 +19,16 @@ class Foo { } // Inflight method - inflight fooInc() { + public inflight fooInc() { // Call the SDK built in resource's inflight method from our inflight code this.c.inc(); } - inflight fooGet(): num { + public inflight fooGet(): num { return this.c.peek(); } - static inflight fooStatic(): str { + public static inflight fooStatic(): str { return "foo static"; } } @@ -43,7 +43,7 @@ class Bar { name: str; b: cloud.Bucket; // Use a user defined resource inside another user defined resource - foo: Foo; + public foo: Foo; // Use an enum inside a user defined resource to verify enum capturing works e: MyEnum; @@ -58,7 +58,7 @@ class Bar { return "bar static"; } - inflight myMethod(): str { + public inflight myMethod(): str { // Call user defined inflight code from another user defined resource this.foo.fooInc(); @@ -69,7 +69,7 @@ class Bar { return this.b.get("foo"); } - inflight testTypeAccess() { + public inflight testTypeAccess() { // We purposefully run these test in an inner scope to validate the compiler analyzes the code // correctly and finds type access in inner scopes. if true { @@ -124,13 +124,13 @@ class BigPublisher { }); } - inflight publish(s: str) { + public inflight publish(s: str) { this.t.publish(s); this.q.push(s); this.b2.put("foo", s); } - inflight getObjectCount(): num { + public inflight getObjectCount(): num { return this.b.list().length; } } diff --git a/examples/tests/valid/resource_call_static.w b/examples/tests/valid/resource_call_static.w index f9427b190a7..dc543183691 100644 --- a/examples/tests/valid/resource_call_static.w +++ b/examples/tests/valid/resource_call_static.w @@ -3,7 +3,7 @@ bring cloud; let globalCounter = new cloud.Counter(); class Another { - static inflight myStaticMethod(): num { + public static inflight myStaticMethod(): num { return globalCounter.peek(); } } diff --git a/examples/tests/valid/resource_captures.w b/examples/tests/valid/resource_captures.w index 3db9d76aa3d..5e51956b055 100644 --- a/examples/tests/valid/resource_captures.w +++ b/examples/tests/valid/resource_captures.w @@ -1,7 +1,7 @@ bring cloud; class First { - myResource: cloud.Bucket; + public myResource: cloud.Bucket; init() { this.myResource = new cloud.Bucket(); @@ -9,19 +9,19 @@ class First { } class Another { - myField: str; - first: First; + public myField: str; + public first: First; init () { this.myField = "hello!"; this.first = new First(); } - inflight meaningOfLife(): num { + public inflight meaningOfLife(): num { return 42; } - inflight anotherFunc(): str { + public inflight anotherFunc(): str { return "42"; } } @@ -67,13 +67,13 @@ class MyResource { this.unusedResource = new cloud.Counter(); } - inflight testNoCapture() { + public inflight testNoCapture() { let arr = [1,2,3]; assert(arr.length == 3); log("array.len=${arr.length}"); } - inflight testCaptureCollectionsOfData() { + public inflight testCaptureCollectionsOfData() { assert(this.arrayOfStr.length == 2); assert(this.arrayOfStr.at(0) == "s1"); assert(this.arrayOfStr.at(1) == "s2"); @@ -84,13 +84,13 @@ class MyResource { assert(!this.setOfStr.has("s3")); } - inflight testCapturePrimitives() { + public inflight testCapturePrimitives() { assert(this.myStr == "myString"); assert(this.myNum == 42); assert(this.myBool == true); } - inflight testCaptureOptional() { + public inflight testCaptureOptional() { assert(this.myOptStr ?? "" == "myOptString"); } @@ -98,39 +98,39 @@ class MyResource { return this.another; } - inflight testCaptureResource() { + public inflight testCaptureResource() { this.myResource.put("f1.txt", "f1"); assert(this.myResource.get("f1.txt") == "f1"); assert(this.myResource.list().length == 1); } - inflight testNestedInflightField() { + public inflight testNestedInflightField() { assert(this.another.myField == "hello!"); log("field=${this.another.myField}"); } - inflight testNestedResource() { + public inflight testNestedResource() { assert(this.another.first.myResource.list().length == 0); this.another.first.myResource.put("hello", this.myStr); log("this.another.first.myResource:${this.another.first.myResource.get("hello")}"); } // expression within an expression - inflight testExpressionRecursive() { + public inflight testExpressionRecursive() { this.myQueue.push(this.myStr); } - inflight testExternal() { + public inflight testExternal() { assert(this.extBucket.list().length == 0); assert(this.extNum == 12); } - inflight testUserDefinedResource() { + public inflight testUserDefinedResource() { assert(this.another.meaningOfLife() == 42); assert(this.another.anotherFunc() == "42"); } - inflight testInflightField() { + public inflight testInflightField() { assert(this.inflightField == 123); } } diff --git a/examples/tests/valid/resource_captures_globals.w b/examples/tests/valid/resource_captures_globals.w index 67ad768d502..ed0b2674ec7 100644 --- a/examples/tests/valid/resource_captures_globals.w +++ b/examples/tests/valid/resource_captures_globals.w @@ -10,7 +10,7 @@ let globalMapOfNum = Map{ "a" => -5, "b" => 2 }; let globalSetOfStr = Set{ "a", "b" }; class First { - myResource: cloud.Bucket; + public myResource: cloud.Bucket; init() { this.myResource = new cloud.Bucket(); @@ -18,8 +18,8 @@ class First { } class Another { - myField: str; - first: First; + public myField: str; + public first: First; init () { this.myField = "hello!"; @@ -30,12 +30,12 @@ class Another { assert(globalCounter.peek() == 0); } - inflight myMethod(): num { + public inflight myMethod(): num { globalCounter.inc(); return globalCounter.peek(); } - static inflight myStaticMethod(): num { + public static inflight myStaticMethod(): num { return globalCounter.peek(); } } @@ -59,7 +59,7 @@ class MyResource { this.localTopic.onMessage(new R()); } - inflight myPut() { + public inflight myPut() { this.localTopic.publish("hello"); globalBucket.put("key", "value"); assert(globalStr == "hello"); diff --git a/examples/tests/valid/static_members.w b/examples/tests/valid/static_members.w index fae8e3e1691..12a206313a9 100644 --- a/examples/tests/valid/static_members.w +++ b/examples/tests/valid/static_members.w @@ -1,13 +1,13 @@ bring cloud; class Foo { - instanceField: num; + public instanceField: num; // TODO: Static field initialization not supported yet (https://github.com/winglang/wing/issues/1668) // static staticField: str = "Static resource value"; // static inflight inflightStaticField: str = "Inflight static resource value"; - static m(): num { return 99; } + public static m(): num { return 99; } init() { this.instanceField = 100; @@ -27,10 +27,10 @@ assert(Foo.m() == 99); test "test" { inflight class InflightClass { init() {} - inflight inflightMethod(): str { + public inflight inflightMethod(): str { return "Inflight method"; } - static inflight staticInflightMethod(): str { + public static inflight staticInflightMethod(): str { return "Static inflight method"; } diff --git a/examples/tests/valid/store.w b/examples/tests/valid/store.w index 4f80fb24e01..f13058e9a23 100644 --- a/examples/tests/valid/store.w +++ b/examples/tests/valid/store.w @@ -14,7 +14,7 @@ class Store { this.b.put("data.txt", ""); }); } - inflight store(data: str) { + public inflight store(data: str) { this.b.put("data.txt", data); } } diff --git a/examples/tests/valid/subdir/bar.w b/examples/tests/valid/subdir/bar.w index 12c36fd5f7f..2a88e40f87d 100644 --- a/examples/tests/valid/subdir/bar.w +++ b/examples/tests/valid/subdir/bar.w @@ -1,7 +1,7 @@ // used by bring_local_normalization.w class Bar { - static bar(): str { + public static bar(): str { return "bar"; } } diff --git a/examples/tests/valid/subdir/foo.w b/examples/tests/valid/subdir/foo.w index b52d46a3895..235fae8b12b 100644 --- a/examples/tests/valid/subdir/foo.w +++ b/examples/tests/valid/subdir/foo.w @@ -4,13 +4,13 @@ bring "./bar.w" as bar; bring "../baz.w" as baz; class Foo { - static foo(): str { + public static foo(): str { return "foo"; } - static bar(): str { + public static bar(): str { return bar.Bar.bar(); } - static baz(): str { + public static baz(): str { return baz.Baz.baz(); } } diff --git a/examples/tests/valid/super_call.w b/examples/tests/valid/super_call.w index 046aa48130f..17cfce8a58e 100644 --- a/examples/tests/valid/super_call.w +++ b/examples/tests/valid/super_call.w @@ -23,7 +23,7 @@ class D extends C { } class E extends D { - description(): str { + public description(): str { return "E extends ${super.description()}"; } } @@ -40,7 +40,7 @@ inflight class InflightA { // Test super calls on inflight classes inflight class InflightB extends InflightA { - description(): str { + public description(): str { return "InflightB extends ${super.description()}"; } } @@ -60,7 +60,7 @@ class BaseClass { } class ExtendedClass extends BaseClass { - inflight do(): str { + public inflight do(): str { b.put("k", "value"); // This should require write access to b return super.do(); // We expect to add binding permissions based on what `super.do()` requires (read) } diff --git a/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap b/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap index 0a014c0fb8e..e1a61bbbe0b 100644 --- a/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap +++ b/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap @@ -2,4 +2,5 @@ source: libs/wingc/src/jsify/tests.rs --- ## Errors +Cannot access private member b of Derived 12:13 Cannot qualify access to a lifted object of type "Bucket" (see https://github.com/winglang/wing/issues/76 for more details) 12:8 diff --git a/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap b/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap index d0946e458d3..353225a96a4 100644 --- a/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap +++ b/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap @@ -2,4 +2,5 @@ source: libs/wingc/src/jsify/tests.rs --- ## Errors +Cannot access private member staticMethod of MyType 6:17 Cannot call into preflight phase while inflight 6:10 From 6f628942c8526e2c6dbf9296d6b728a86944822b Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 14:33:18 +0300 Subject: [PATCH 23/56] added missing `public` to sdk tests --- examples/tests/sdk_tests/function/logging.w | 2 +- examples/tests/sdk_tests/queue/set_consumer.w | 2 +- examples/tests/sdk_tests/topic/on_message.w | 2 +- examples/tests/sdk_tests/util/sleep.w | 2 +- examples/tests/sdk_tests/util/uuidv4.w | 4 ++-- examples/tests/sdk_tests/util/wait-until.w | 2 +- examples/tests/sdk_tests/website/website.w | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/tests/sdk_tests/function/logging.w b/examples/tests/sdk_tests/function/logging.w index 0fa007c92b2..dc77a7bec0e 100644 --- a/examples/tests/sdk_tests/function/logging.w +++ b/examples/tests/sdk_tests/function/logging.w @@ -1,7 +1,7 @@ bring cloud; class Util { - extern "./logging.js" static inflight logging(): void; + extern "./logging.js" public static inflight logging(): void; } let f1 = new cloud.Function(inflight (input: str): void => { diff --git a/examples/tests/sdk_tests/queue/set_consumer.w b/examples/tests/sdk_tests/queue/set_consumer.w index 0119929cbed..51a52e1fdce 100644 --- a/examples/tests/sdk_tests/queue/set_consumer.w +++ b/examples/tests/sdk_tests/queue/set_consumer.w @@ -12,7 +12,7 @@ class Predicate { this.c = c; } - inflight test(): bool{ + public inflight test(): bool{ return this.c.peek() == 2; } } diff --git a/examples/tests/sdk_tests/topic/on_message.w b/examples/tests/sdk_tests/topic/on_message.w index 563825e949d..a83f9b39c8c 100644 --- a/examples/tests/sdk_tests/topic/on_message.w +++ b/examples/tests/sdk_tests/topic/on_message.w @@ -10,7 +10,7 @@ class Predicate { this.c = c; } - inflight test(): bool{ + public inflight test(): bool{ return this.c.peek() == 10; } } diff --git a/examples/tests/sdk_tests/util/sleep.w b/examples/tests/sdk_tests/util/sleep.w index 80de505b1c6..b67f01fb60c 100644 --- a/examples/tests/sdk_tests/util/sleep.w +++ b/examples/tests/sdk_tests/util/sleep.w @@ -1,7 +1,7 @@ bring util; class JSHelper { - extern "./sleep-helper.js" static inflight getTime(): num; + extern "./sleep-helper.js" public static inflight getTime(): num; } let oneHundredMiliseconds = 0.1s; diff --git a/examples/tests/sdk_tests/util/uuidv4.w b/examples/tests/sdk_tests/util/uuidv4.w index 4dfbfb6d216..b03bef30aba 100644 --- a/examples/tests/sdk_tests/util/uuidv4.w +++ b/examples/tests/sdk_tests/util/uuidv4.w @@ -1,14 +1,14 @@ bring util; class JSHelper { - extern "./uuidv4-helper.js" static validateUUIDv4(uuidv4: str): bool; + extern "./uuidv4-helper.js" public static validateUUIDv4(uuidv4: str): bool; } let data = util.uuidv4(); assert(JSHelper.validateUUIDv4(data) == true); class JSHelperInflight { - extern "./uuidv4-helper.js" static inflight validateUUIDv4(uuidv4: str): bool; + extern "./uuidv4-helper.js" public static inflight validateUUIDv4(uuidv4: str): bool; } test "inflight uuidv4" { diff --git a/examples/tests/sdk_tests/util/wait-until.w b/examples/tests/sdk_tests/util/wait-until.w index 73e5bbee064..2c67715adb4 100644 --- a/examples/tests/sdk_tests/util/wait-until.w +++ b/examples/tests/sdk_tests/util/wait-until.w @@ -2,7 +2,7 @@ bring cloud; bring util; class JSHelper { - extern "./sleep-helper.js" static inflight getTime(): num; + extern "./sleep-helper.js" public static inflight getTime(): num; } let invokeCounter = new cloud.Counter(); diff --git a/examples/tests/sdk_tests/website/website.w b/examples/tests/sdk_tests/website/website.w index 83703fdaa18..3cff75740ff 100644 --- a/examples/tests/sdk_tests/website/website.w +++ b/examples/tests/sdk_tests/website/website.w @@ -5,7 +5,7 @@ let w = new cloud.Website(path: "./website"); let config = Json { json: 1 }; class Util { - extern "../external/fs.js" static readFile(path: str): str; + extern "../external/fs.js" public static readFile(path: str): str; } let indexFile = Util.readFile("./website/website/index.html"); From e1d26f460163eebf7f4bcc412ecb367a349d9769 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 14:34:10 +0300 Subject: [PATCH 24/56] added access_modifiers test results to snapshot --- tools/hangar/__snapshots__/invalid.ts.snap | 232 ++++++++++++++++++++- 1 file changed, 225 insertions(+), 7 deletions(-) diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 35674fef90b..8e36b53d395 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -10,6 +10,105 @@ exports[`access_hidden_namespace.w 1`] = ` +Tests 1 failed (1) +Test Files 1 failed (1) +Duration " +`; + +exports[`access_modifiers.w 1`] = ` +"error: Cannot access protected member protected_field of Foo + --> ../../../examples/tests/invalid/access_modifiers.w:64:9 + | +64 | log(foo.protected_field); + | ^^^^^^^^^^^^^^^ Cannot access protected member protected_field of Foo + + +error: Cannot access private member private_field of Foo + --> ../../../examples/tests/invalid/access_modifiers.w:66:9 + | +66 | log(foo.private_field); + | ^^^^^^^^^^^^^ Cannot access private member private_field of Foo + + +error: Cannot access protected member protected_static_method of Foo + --> ../../../examples/tests/invalid/access_modifiers.w:70:5 + | +70 | Foo.protected_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member protected_static_method of Foo + + +error: Cannot access private member private_static_method of Foo + --> ../../../examples/tests/invalid/access_modifiers.w:72:5 + | +72 | Foo.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member private_static_method of Foo + + +error: Cannot access protected member protected_static_method of Foo + --> ../../../examples/tests/invalid/access_modifiers.w:92:9 + | +92 | Foo.protected_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member protected_static_method of Foo + + +error: Cannot access private member private_static_method of Foo + --> ../../../examples/tests/invalid/access_modifiers.w:94:9 + | +94 | Foo.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member private_static_method of Foo + + +error: Cannot access protected member protected_field of Foo + --> ../../../examples/tests/invalid/access_modifiers.w:78:13 + | +78 | log(foo.protected_field); + | ^^^^^^^^^^^^^^^ Cannot access protected member protected_field of Foo + + +error: Cannot access private member private_field of Foo + --> ../../../examples/tests/invalid/access_modifiers.w:80:13 + | +80 | log(foo.private_field); + | ^^^^^^^^^^^^^ Cannot access private member private_field of Foo + + +error: Cannot access protected member protected_method of Foo + --> ../../../examples/tests/invalid/access_modifiers.w:84:9 + | +84 | foo.protected_method(); + | ^^^^^^^^^^^^^^^^ Cannot access protected member protected_method of Foo + + +error: Cannot access private member private_method of Foo + --> ../../../examples/tests/invalid/access_modifiers.w:86:9 + | +86 | foo.private_method(); + | ^^^^^^^^^^^^^^ Cannot access private member private_method of Foo + + +error: Cannot access private member private_static_method of Foo + --> ../../../examples/tests/invalid/access_modifiers.w:57:9 + | +57 | Foo.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member private_static_method of Foo + + +error: Cannot access private member private_field of Bar + --> ../../../examples/tests/invalid/access_modifiers.w:44:14 + | +44 | log(this.private_field); + | ^^^^^^^^^^^^^ Cannot access private member private_field of Bar + + +error: Cannot access private member private_method of Bar + --> ../../../examples/tests/invalid/access_modifiers.w:49:10 + | +49 | this.private_method(); + | ^^^^^^^^^^^^^^ Cannot access private member private_method of Bar + + + + Tests 1 failed (1) Test Files 1 failed (1) Duration " @@ -23,6 +122,13 @@ exports[`access_static_from_instance.w 1`] = ` | ^^^^^^^^^^^^^^ Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 +error: Cannot access private member f of Foo + --> ../../../examples/tests/invalid/access_static_from_instance.w:19:5 + | +19 | foo.f; // Can't access static fields through instances + | ^ Cannot access private member f of Foo + + error: Cannot access static property \\"f\\" from instance --> ../../../examples/tests/invalid/access_static_from_instance.w:19:5 | @@ -30,6 +136,13 @@ error: Cannot access static property \\"f\\" from instance | ^ Cannot access static property \\"f\\" from instance +error: Cannot access private member m of Foo + --> ../../../examples/tests/invalid/access_static_from_instance.w:20:5 + | +20 | foo.m(); // Can't access static methods through instances + | ^ Cannot access private member m of Foo + + error: Cannot access static property \\"m\\" from instance --> ../../../examples/tests/invalid/access_static_from_instance.w:20:5 | @@ -197,6 +310,13 @@ exports[`call_inflight_from_preflight.w 1`] = ` | ^^^^^^^^^^^^^^ Cannot call into inflight phase while preflight +error: Cannot access private member do of Foo + --> ../../../examples/tests/invalid/call_inflight_from_preflight.w:12:5 + | +12 | foo.do(); + | ^^ Cannot access private member do of Foo + + error: Cannot call into inflight phase while preflight --> ../../../examples/tests/invalid/call_inflight_from_preflight.w:12:1 | @@ -1225,7 +1345,49 @@ Duration " `; exports[`inflight_ref_explicit_ops.w 1`] = ` -"error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) +"error: Cannot access private member test4 of Test + --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:60:18 + | +60 | test \\"test4\\" { f.test4(); } + | ^^^^^ Cannot access private member test4 of Test + + +error: Cannot access private member test3 of Test + --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:59:18 + | +59 | test \\"test3\\" { f.test3(); } + | ^^^^^ Cannot access private member test3 of Test + + +error: Cannot access private member test2 of Test + --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:58:18 + | +58 | test \\"test2\\" { f.test2(); } + | ^^^^^ Cannot access private member test2 of Test + + +error: Cannot access private member test1 of Test + --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:57:18 + | +57 | test \\"test1\\" { f.test1(); } + | ^^^^^ Cannot access private member test1 of Test + + +error: Cannot access private member anotherStr of Another + --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:52:25 + | +52 | assert(this.another.anotherStr == \\"bang\\"); + | ^^^^^^^^^^ Cannot access private member anotherStr of Another + + +error: Cannot access private member inflightReturnsResource of Another + --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:42:26 + | +42 | let q = this.another.inflightReturnsResource(); + | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member inflightReturnsResource of Another + + +error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:13:12 | 13 | return this.myQueue; @@ -1254,7 +1416,28 @@ Duration " `; exports[`inflight_ref_resource_sub_method.w 1`] = ` -"error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) +"error: Cannot access private member test of Test + --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:40:17 + | +40 | test \\"test\\" { f.test(); } + | ^^^^ Cannot access private member test of Test + + +error: Cannot access private member inflightReturnsResource of Another + --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:31:26 + | +31 | let q = this.another.inflightReturnsResource(); + | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member inflightReturnsResource of Another + + +error: Cannot access private member inflightReturnsResource2 of Another + --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:34:27 + | +34 | let q2 = this.another.inflightReturnsResource2(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member inflightReturnsResource2 of Another + + +error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:13:12 | 13 | return this.myQueue; @@ -1276,7 +1459,14 @@ Duration " `; exports[`inflight_ref_unknown_op.w 1`] = ` -"error: Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) +"error: Cannot access private member test of Test + --> ../../../examples/tests/invalid/inflight_ref_unknown_op.w:24:17 + | +24 | test \\"test\\" { f.test(); } + | ^^^^ Cannot access private member test of Test + + +error: Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) --> ../../../examples/tests/invalid/inflight_ref_unknown_op.w:13:13 | 13 | let x = this.b; @@ -1686,6 +1876,13 @@ error: Cannot assign nil value to variables without explicit optional type | ^^^^^^^^^^^^^^^ Cannot assign nil value to variables without explicit optional type +error: Cannot access private member setBar of Foo + --> ../../../examples/tests/invalid/nil.w:20:7 + | +20 | foo.setBar(nil); + | ^^^^^^ Cannot access private member setBar of Foo + + error: Expected type to be \\"num\\", but got \\"nil\\" instead (hint: to allow \\"nil\\" assignment use optional type: \\"num?\\") --> ../../../examples/tests/invalid/nil.w:20:14 | @@ -1817,7 +2014,14 @@ Duration " exports[`panic.w 2`] = `"Panicked, backtrace not captured: Unsupported"`; exports[`preflight_from_inflight.w 1`] = ` -"error: Cannot call into preflight phase while inflight +"error: Cannot access private member myPreflight of MyResource + --> ../../../examples/tests/invalid/preflight_from_inflight.w:15:12 + | +15 | this.r.myPreflight(); + | ^^^^^^^^^^^ Cannot access private member myPreflight of MyResource + + +error: Cannot call into preflight phase while inflight --> ../../../examples/tests/invalid/preflight_from_inflight.w:15:5 | 15 | this.r.myPreflight(); @@ -1896,6 +2100,13 @@ error: Variable is not reassignable | ^^^^^^ Variable is not reassignable +error: Cannot access private member inner of InnerR + --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:30:17 + | +30 | this.innerR.inner = 2; + | ^^^^^ Cannot access private member inner of InnerR + + error: Variable is not reassignable --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:30:5 | @@ -1911,7 +2122,14 @@ Duration " `; exports[`resource_access_field_as_method.w 1`] = ` -"error: Expected a function or method, found \\"str\\" +"error: Cannot access private member name of SomeResource + --> ../../../examples/tests/invalid/resource_access_field_as_method.w:9:3 + | +9 | x.name(); + | ^^^^ Cannot access private member name of SomeResource + + +error: Expected a function or method, found \\"str\\" --> ../../../examples/tests/invalid/resource_access_field_as_method.w:9:1 | 9 | x.name(); @@ -2506,11 +2724,11 @@ Duration " `; exports[`unknown_field.w 1`] = ` -"error: No member \\"a\\" in class \\"String\\" +"error: Unknown symbol \\"a\\" --> ../../../examples/tests/invalid/unknown_field.w:1:12 | 1 | std.String.a.b.c.fromJson(); - | ^ No member \\"a\\" in class \\"String\\" + | ^ Unknown symbol \\"a\\" From 121fb6cdb8a377c1b44fb19473aff28eee75c60e Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 17:32:53 +0300 Subject: [PATCH 25/56] fixes after merge --- libs/wingc/src/closure_transform.rs | 6 +++--- libs/wingc/src/jsify.rs | 10 +++------- libs/wingc/src/parser.rs | 8 ++++---- libs/wingc/src/type_check.rs | 15 +++++++++++---- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/libs/wingc/src/closure_transform.rs b/libs/wingc/src/closure_transform.rs index 04cb637b869..1e5c9abadde 100644 --- a/libs/wingc/src/closure_transform.rs +++ b/libs/wingc/src/closure_transform.rs @@ -2,9 +2,9 @@ use indexmap::IndexMap; use crate::{ ast::{ - AccessModifier, ArgList, CalleeKind, Class, ClassField, Expr, ExprKind, FunctionBody, FunctionDefinition, - FunctionParameter, FunctionSignature, Literal, NewExpr, Phase, Reference, Scope, Stmt, StmtKind, Symbol, - TypeAnnotation, TypeAnnotationKind, UserDefinedType, + AccessModifier, ArgList, AssignmentKind, CalleeKind, Class, ClassField, Expr, ExprKind, FunctionBody, + FunctionDefinition, FunctionParameter, FunctionSignature, Literal, NewExpr, Phase, Reference, Scope, Stmt, + StmtKind, Symbol, TypeAnnotation, TypeAnnotationKind, UserDefinedType, }, diagnostic::WingSpan, fold::{self, Fold}, diff --git a/libs/wingc/src/jsify.rs b/libs/wingc/src/jsify.rs index 221f15fe678..1fbca8334a8 100644 --- a/libs/wingc/src/jsify.rs +++ b/libs/wingc/src/jsify.rs @@ -10,9 +10,9 @@ use std::{borrow::Borrow, cell::RefCell, cmp::Ordering, collections::BTreeMap, v use crate::{ ast::{ - ArgList, BinaryOperator, BringSource, CalleeKind, Class as AstClass, ElifLetBlock, Expr, ExprKind, FunctionBody, - FunctionDefinition, IfLet, InterpolatedStringPart, Literal, NewExpr, Phase, Reference, Scope, Stmt, StmtKind, - StructField, Symbol, TypeAnnotationKind, UnaryOperator, UserDefinedType, + ArgList, AssignmentKind, BinaryOperator, BringSource, CalleeKind, Class as AstClass, ElifLetBlock, Expr, ExprKind, + FunctionBody, FunctionDefinition, IfLet, InterpolatedStringPart, Literal, NewExpr, Phase, Reference, Scope, Stmt, + StmtKind, Symbol, UnaryOperator, UserDefinedType, }, comp_ctx::{CompilationContext, CompilationPhase}, dbg_panic, debug, @@ -1502,10 +1502,6 @@ fn get_public_symbols(scope: &Scope) -> Vec { symbols } -fn struct_filename(s: &String) -> String { - format!("./{}.Struct.js", s) -} - fn lookup_span(span: &WingSpan, files: &Files) -> String { let source = files .get_file(&span.file_id) diff --git a/libs/wingc/src/parser.rs b/libs/wingc/src/parser.rs index a4b69c14bfa..2461143b6d4 100644 --- a/libs/wingc/src/parser.rs +++ b/libs/wingc/src/parser.rs @@ -8,10 +8,10 @@ use tree_sitter::Node; use tree_sitter_traversal::{traverse, Order}; use crate::ast::{ - AccessModifier, ArgList, BinaryOperator, BringSource, CalleeKind, CatchBlock, Class, ClassField, ElifBlock, - ElifLetBlock, Expr, ExprKind, FunctionBody, FunctionDefinition, FunctionParameter, FunctionSignature, IfLet, - Interface, InterpolatedString, InterpolatedStringPart, Literal, NewExpr, Phase, Reference, Scope, Stmt, StmtKind, - StructField, Symbol, TypeAnnotation, TypeAnnotationKind, UnaryOperator, UserDefinedType, + AccessModifier, ArgList, AssignmentKind, BinaryOperator, BringSource, CalleeKind, CatchBlock, Class, ClassField, + ElifBlock, ElifLetBlock, Expr, ExprKind, FunctionBody, FunctionDefinition, FunctionParameter, FunctionSignature, + IfLet, Interface, InterpolatedString, InterpolatedStringPart, Literal, NewExpr, Phase, Reference, Scope, Stmt, + StmtKind, StructField, Symbol, TypeAnnotation, TypeAnnotationKind, UnaryOperator, UserDefinedType, }; use crate::comp_ctx::{CompilationContext, CompilationPhase}; use crate::diagnostic::{report_diagnostic, Diagnostic, DiagnosticResult, WingSpan}; diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 068d5563f2f..df13ed34f9f 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -5,8 +5,8 @@ pub mod lifts; pub mod symbol_env; use crate::ast::{ - self, AccessModifier, BringSource, CalleeKind, ClassField, ExprId, FunctionDefinition, IfLet, NewExpr, - TypeAnnotationKind, + self, AccessModifier, AssignmentKind, BringSource, CalleeKind, ClassField, ExprId, FunctionDefinition, IfLet, + NewExpr, TypeAnnotationKind, }; use crate::ast::{ ArgList, BinaryOperator, Class as AstClass, Expr, ExprKind, FunctionBody, FunctionParameter as AstFunctionParameter, @@ -3650,7 +3650,14 @@ impl<'a> TypeChecker<'a> { // alias is the symbol we are giving to the imported library or namespace } - fn type_check_assignment(&mut self, kind: AssignmentKind, value: &Expr, env: &mut SymbolEnv, variable: &Reference, stmt: &Stmt) { + fn type_check_assignment( + &mut self, + kind: &AssignmentKind, + value: &Expr, + env: &mut SymbolEnv, + variable: &Reference, + stmt: &Stmt, + ) { let (exp_type, _) = self.type_check_exp(value, env); // TODO: we need to verify that if this variable is defined in a parent environment (i.e. @@ -3664,7 +3671,7 @@ impl<'a> TypeChecker<'a> { self.spanned_error(stmt, "Variable cannot be reassigned from inflight".to_string()); } - if matches!(&kind, AssignmentKind::AssignIncr | AssignmentKind::AssignDecr) { + if matches!(kind, AssignmentKind::AssignIncr | AssignmentKind::AssignDecr) { self.validate_type(exp_type, self.types.number(), value); self.validate_type(var.type_, self.types.number(), variable); } From 8f78f26b9f95d61fd2e0eb605500642bc3d3de34 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 18:15:36 +0300 Subject: [PATCH 26/56] cleanup --- libs/wingc/src/lifting.rs | 9 --------- libs/wingc/src/type_check.rs | 25 +------------------------ 2 files changed, 1 insertion(+), 33 deletions(-) diff --git a/libs/wingc/src/lifting.rs b/libs/wingc/src/lifting.rs index c2357b25b1d..7db1fb698e7 100644 --- a/libs/wingc/src/lifting.rs +++ b/libs/wingc/src/lifting.rs @@ -336,15 +336,6 @@ impl<'a> Visit<'a> for LiftVisitor<'a> { return; } - // extract the "env" from the class initializer and push it to the context - // because this is the environment in which we want to resolve references - // as oppose to the environment of the class definition itself. - // let init_env = if let FunctionBody::Statements(ref s) = node.initializer.body { - // Some(self.jsify.types.get_scope_env(&s)) - // } else { - // None - // }; - let udt = UserDefinedType { root: node.name.clone(), fields: vec![], diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index df13ed34f9f..6c26734fd99 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -4734,9 +4734,7 @@ impl<'a> TypeChecker<'a> { let v = self.get_property_from_class_like(new_class.as_class().unwrap(), property, true, env); (v, Phase::Independent) } - Type::Class(ref c) => - /*match c.env.lookup(&property, None)*/ - { + Type::Class(ref c) => { let v = self.get_property_from_class_like(c, property, true, env); if matches!(v.kind, VariableKind::InstanceMember) { return self.spanned_error_with_var( @@ -4745,27 +4743,6 @@ impl<'a> TypeChecker<'a> { ); } (v.clone(), v.phase) - // Some(SymbolKind::Variable(v)) => { - // if let VariableKind::StaticMember = v.kind { - // // Validate access modifier - // if !v.type_.is_unresolved() { - // self.check_access(env, type_, property, v.access_modifier); - // } - // (v.clone(), v.phase) - // } else { - // self.spanned_error_with_var( - // property, - // format!( - // "Class \"{}\" contains a member \"{}\" but it is not static", - // type_, property.name - // ), - // ) - // } - // } - // _ => self.spanned_error_with_var( - // property, - // format!("No member \"{}\" in class \"{}\"", property.name, type_), - // ), } _ => self.spanned_error_with_var(property, format!("\"{}\" not a valid reference", reference)), } From 303050f99b1568b4f764376c4d762beef49831c4 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 18:23:38 +0300 Subject: [PATCH 27/56] fix test --- examples/tests/valid/assertions.w | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/tests/valid/assertions.w b/examples/tests/valid/assertions.w index d406d818bee..bdaae595461 100644 --- a/examples/tests/valid/assertions.w +++ b/examples/tests/valid/assertions.w @@ -1,5 +1,5 @@ inflight class Assert { - static equalStr(a: str, b: str): bool { + public static equalStr(a: str, b: str): bool { try { assert(a == b); } catch e { @@ -7,7 +7,7 @@ inflight class Assert { } } - static isNil(a: str?): bool { + public static isNil(a: str?): bool { try { assert(a == nil); } catch e { @@ -16,7 +16,7 @@ inflight class Assert { } } - static equalNum(a: num, b: num): bool{ + public static equalNum(a: num, b: num): bool{ try { assert(a == b); } catch e { From 2acf609e7e4df380b8b620e431f915a2d7b2731e Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Sun, 10 Sep 2023 18:55:37 +0300 Subject: [PATCH 28/56] no need to pass stmt everywhere, use ctx --- libs/wingc/src/type_check.rs | 106 ++++++++++++++++------------------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 6c26734fd99..e973656eedb 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -2979,21 +2979,21 @@ impl<'a> TypeChecker<'a> { initial_value, type_, } => { - tc.type_check_let(type_, env, initial_value, var_name, reassignable, stmt); // TODO: do we now need to pass stmt everywhere when we can get it from the ctx? + tc.type_check_let(type_, env, initial_value, var_name, reassignable); } StmtKind::ForLoop { iterator, iterable, statements, } => { - tc.type_check_for_loop(iterable, env, stmt, iterator, statements); + tc.type_check_for_loop(iterable, env, iterator, statements); } StmtKind::While { condition, statements } => { - tc.type_check_while(condition, env, stmt, statements); + tc.type_check_while(condition, env, statements); } StmtKind::Break | StmtKind::Continue => {} StmtKind::IfLet(iflet) => { - tc.type_check_iflet(env, stmt, iflet); + tc.type_check_iflet(env, iflet); } StmtKind::If { condition, @@ -3001,13 +3001,13 @@ impl<'a> TypeChecker<'a> { elif_statements, else_statements, } => { - tc.type_check_if(condition, statements, stmt, env, elif_statements, else_statements); + tc.type_check_if(condition, statements, env, elif_statements, else_statements); } StmtKind::Expression(e) => { tc.type_check_exp(e, env); } StmtKind::Assignment { kind, variable, value } => { - tc.type_check_assignment(kind, value, env, variable, stmt); + tc.type_check_assignment(kind, value, env, variable); } StmtKind::Bring { source, identifier } => { tc.type_check_bring(source, identifier, stmt, env); @@ -3032,10 +3032,10 @@ impl<'a> TypeChecker<'a> { tc.type_check_class(env, stmt, ast_class); } StmtKind::Interface(AstInterface { name, methods, extends }) => { - tc.type_check_interface(env, stmt, extends, name, methods); + tc.type_check_interface(env, extends, name, methods); } StmtKind::Struct { name, extends, fields } => { - tc.type_check_struct(stmt, fields, env, extends, name); + tc.type_check_struct(fields, env, extends, name); } StmtKind::Enum { name, values } => { tc.type_check_enum(name, values, env); @@ -3045,7 +3045,7 @@ impl<'a> TypeChecker<'a> { catch_block, finally_statements, } => { - tc.type_check_try_catch(env, stmt, try_statements, catch_block, finally_statements); + tc.type_check_try_catch(env, try_statements, catch_block, finally_statements); } StmtKind::CompilerDebugEnv => { println!("[symbol environment at {}]", stmt.span); @@ -3060,7 +3060,6 @@ impl<'a> TypeChecker<'a> { fn type_check_try_catch( &mut self, env: &mut SymbolEnv, - stmt: &Stmt, try_statements: &Scope, catch_block: &Option, finally_statements: &Option, @@ -3070,7 +3069,7 @@ impl<'a> TypeChecker<'a> { Some(env.get_ref()), SymbolEnvKind::Scope, env.phase, - stmt.idx, + self.ctx.current_stmt_idx(), )); self.types.set_scope_env(try_statements, try_env); self.inner_scopes.push((try_statements, self.ctx.clone())); @@ -3081,7 +3080,7 @@ impl<'a> TypeChecker<'a> { Some(env.get_ref()), SymbolEnvKind::Scope, env.phase, - stmt.idx, + self.ctx.current_stmt_idx(), )); // Add the exception variable to the catch block @@ -3107,7 +3106,7 @@ impl<'a> TypeChecker<'a> { Some(env.get_ref()), SymbolEnvKind::Scope, env.phase, - stmt.idx, + self.ctx.current_stmt_idx(), )); self.types.set_scope_env(finally_statements, finally_env); self.inner_scopes.push((finally_statements, self.ctx.clone())); @@ -3131,7 +3130,6 @@ impl<'a> TypeChecker<'a> { fn type_check_struct( &mut self, - stmt: &Stmt, fields: &Vec, env: &mut SymbolEnv, extends: &Vec, @@ -3146,7 +3144,7 @@ impl<'a> TypeChecker<'a> { None, SymbolEnvKind::Type(self.types.void()), Phase::Independent, - stmt.idx, + self.ctx.current_stmt_idx(), ); // Collect types this struct extends @@ -3154,7 +3152,7 @@ impl<'a> TypeChecker<'a> { .iter() .filter_map(|ext| { let t = self - .resolve_user_defined_type(ext, env, stmt.idx) + .resolve_user_defined_type(ext, env, self.ctx.current_stmt_idx()) .unwrap_or_else(|e| self.type_error(e)); if t.as_struct().is_some() { Some(t) @@ -3174,7 +3172,12 @@ impl<'a> TypeChecker<'a> { })); // Create the actual environment for the struct - let mut struct_env = SymbolEnv::new(None, SymbolEnvKind::Type(struct_type), Phase::Independent, stmt.idx); + let mut struct_env = SymbolEnv::new( + None, + SymbolEnvKind::Type(struct_type), + Phase::Independent, + self.ctx.current_stmt_idx(), + ); // Add fields to the struct env for field in fields.iter() { @@ -3219,19 +3222,23 @@ impl<'a> TypeChecker<'a> { fn type_check_interface( &mut self, env: &mut SymbolEnv, - stmt: &Stmt, extends: &Vec, name: &Symbol, methods: &Vec<(Symbol, ast::FunctionSignature)>, ) { // Create environment representing this interface, for now it'll be empty just so we can support referencing ourselves from the interface definition. - let dummy_env = SymbolEnv::new(None, SymbolEnvKind::Type(self.types.void()), env.phase, stmt.idx); + let dummy_env = SymbolEnv::new( + None, + SymbolEnvKind::Type(self.types.void()), + env.phase, + self.ctx.current_stmt_idx(), + ); let extend_interfaces = extends .iter() .filter_map(|i| { let t = self - .resolve_user_defined_type(i, env, stmt.idx) + .resolve_user_defined_type(i, env, self.ctx.current_stmt_idx()) .unwrap_or_else(|e| self.type_error(e)); if t.as_interface().is_some() { Some(t) @@ -3261,7 +3268,12 @@ impl<'a> TypeChecker<'a> { }; // Create the real interface environment to be filled with the interface AST types - let mut interface_env = SymbolEnv::new(None, SymbolEnvKind::Type(interface_type), env.phase, stmt.idx); + let mut interface_env = SymbolEnv::new( + None, + SymbolEnvKind::Type(interface_type), + env.phase, + self.ctx.current_stmt_idx(), + ); // Add methods to the interface env for (method_name, sig) in methods.iter() { @@ -3432,7 +3444,6 @@ impl<'a> TypeChecker<'a> { } else { panic!("Expected class type"); } - // let mut class_env = &mut mut_class.env; if let FunctionBody::Statements(scope) = &ast_class.inflight_initializer.body { self.check_class_field_initialization(&scope, &ast_class.fields, Phase::Inflight); @@ -3650,14 +3661,7 @@ impl<'a> TypeChecker<'a> { // alias is the symbol we are giving to the imported library or namespace } - fn type_check_assignment( - &mut self, - kind: &AssignmentKind, - value: &Expr, - env: &mut SymbolEnv, - variable: &Reference, - stmt: &Stmt, - ) { + fn type_check_assignment(&mut self, kind: &AssignmentKind, value: &Expr, env: &mut SymbolEnv, variable: &Reference) { let (exp_type, _) = self.type_check_exp(value, env); // TODO: we need to verify that if this variable is defined in a parent environment (i.e. @@ -3668,7 +3672,7 @@ impl<'a> TypeChecker<'a> { if !var.type_.is_unresolved() && !var.reassignable { self.spanned_error(variable, "Variable is not reassignable".to_string()); } else if var_phase == Phase::Preflight && env.phase == Phase::Inflight { - self.spanned_error(stmt, "Variable cannot be reassigned from inflight".to_string()); + self.spanned_error(variable, "Variable cannot be reassigned from inflight".to_string()); } if matches!(kind, AssignmentKind::AssignIncr | AssignmentKind::AssignDecr) { @@ -3683,15 +3687,14 @@ impl<'a> TypeChecker<'a> { &mut self, condition: &Expr, statements: &Scope, - stmt: &Stmt, env: &mut SymbolEnv, elif_statements: &Vec, else_statements: &Option, ) { - self.type_check_if_statement(condition, statements, stmt, env); + self.type_check_if_statement(condition, statements, env); for elif_scope in elif_statements { - self.type_check_if_statement(&elif_scope.condition, &elif_scope.statements, stmt, env); + self.type_check_if_statement(&elif_scope.condition, &elif_scope.statements, env); } if let Some(else_scope) = else_statements { @@ -3699,20 +3702,19 @@ impl<'a> TypeChecker<'a> { Some(env.get_ref()), SymbolEnvKind::Scope, env.phase, - stmt.idx, + self.ctx.current_stmt_idx(), )); self.types.set_scope_env(else_scope, else_scope_env); self.inner_scopes.push((else_scope, self.ctx.clone())); } } - fn type_check_iflet(&mut self, env: &mut SymbolEnv, stmt: &Stmt, iflet: &IfLet) { + fn type_check_iflet(&mut self, env: &mut SymbolEnv, iflet: &IfLet) { self.type_check_if_let_statement( &iflet.value, &iflet.statements, &iflet.reassignable, &iflet.var_name, - stmt, env, ); @@ -3722,7 +3724,6 @@ impl<'a> TypeChecker<'a> { &elif_scope.statements, &elif_scope.reassignable, &elif_scope.var_name, - stmt, env, ); } @@ -3732,14 +3733,14 @@ impl<'a> TypeChecker<'a> { Some(env.get_ref()), SymbolEnvKind::Scope, env.phase, - stmt.idx, + self.ctx.current_stmt_idx(), )); self.types.set_scope_env(else_scope, else_scope_env); self.inner_scopes.push((else_scope, self.ctx.clone())); } } - fn type_check_while(&mut self, condition: &Expr, env: &mut SymbolEnv, stmt: &Stmt, statements: &Scope) { + fn type_check_while(&mut self, condition: &Expr, env: &mut SymbolEnv, statements: &Scope) { let (cond_type, _) = self.type_check_exp(condition, env); self.validate_type(cond_type, self.types.bool(), condition); @@ -3747,21 +3748,14 @@ impl<'a> TypeChecker<'a> { Some(env.get_ref()), SymbolEnvKind::Scope, env.phase, - stmt.idx, + self.ctx.current_stmt_idx(), )); self.types.set_scope_env(statements, scope_env); self.inner_scopes.push((statements, self.ctx.clone())); } - fn type_check_for_loop( - &mut self, - iterable: &Expr, - env: &mut SymbolEnv, - stmt: &Stmt, - iterator: &Symbol, - statements: &Scope, - ) { + fn type_check_for_loop(&mut self, iterable: &Expr, env: &mut SymbolEnv, iterator: &Symbol, statements: &Scope) { // TODO: Expression must be iterable let (exp_type, _) = self.type_check_exp(iterable, env); @@ -3783,7 +3777,7 @@ impl<'a> TypeChecker<'a> { Some(env.get_ref()), SymbolEnvKind::Scope, env.phase, - stmt.idx, + self.ctx.current_stmt_idx(), )); match scope_env.define( &iterator, @@ -3807,7 +3801,6 @@ impl<'a> TypeChecker<'a> { initial_value: &Expr, var_name: &Symbol, reassignable: &bool, - stmt: &Stmt, ) { let explicit_type = type_.as_ref().map(|t| self.resolve_type_annotation(t, env)); let (mut inferred_type, _) = self.type_check_exp(initial_value, env); @@ -3834,7 +3827,7 @@ impl<'a> TypeChecker<'a> { match env.define( var_name, SymbolKind::make_free_variable(var_name.clone(), final_type, *reassignable, env.phase), - StatementIdx::Index(stmt.idx), + StatementIdx::Index(self.ctx.current_stmt_idx()), ) { Err(type_error) => { self.type_error(type_error); @@ -3851,7 +3844,7 @@ impl<'a> TypeChecker<'a> { match env.define( var_name, SymbolKind::make_free_variable(var_name.clone(), inferred_type, *reassignable, env.phase), - StatementIdx::Index(stmt.idx), + StatementIdx::Index(self.ctx.current_stmt_idx()), ) { Err(type_error) => { self.type_error(type_error); @@ -3867,7 +3860,6 @@ impl<'a> TypeChecker<'a> { statements: &Scope, reassignable: &bool, var_name: &Symbol, - stmt: &Stmt, env: &mut SymbolEnv, ) { let (mut cond_type, _) = self.type_check_exp(value, env); @@ -3899,7 +3891,7 @@ impl<'a> TypeChecker<'a> { Some(env.get_ref()), SymbolEnvKind::Scope, env.phase, - stmt.idx, + self.ctx.current_stmt_idx(), )); // Add the variable to if block scope @@ -3918,7 +3910,7 @@ impl<'a> TypeChecker<'a> { self.inner_scopes.push((statements, self.ctx.clone())); } - fn type_check_if_statement(&mut self, condition: &Expr, statements: &Scope, stmt: &Stmt, env: &mut SymbolEnv) { + fn type_check_if_statement(&mut self, condition: &Expr, statements: &Scope, env: &mut SymbolEnv) { let (cond_type, _) = self.type_check_exp(condition, env); self.validate_type(cond_type, self.types.bool(), condition); @@ -3926,7 +3918,7 @@ impl<'a> TypeChecker<'a> { Some(env.get_ref()), SymbolEnvKind::Scope, env.phase, - stmt.idx, + self.ctx.current_stmt_idx(), )); self.types.set_scope_env(statements, if_scope_env); self.inner_scopes.push((statements, self.ctx.clone())); From 5ac406861faa21d871426003211efd51c2a3166d Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Sun, 10 Sep 2023 16:13:22 +0000 Subject: [PATCH 29/56] chore: self mutation (e2e-2of2.diff) Signed-off-by: monada-bot[bot] --- tools/hangar/__snapshots__/invalid.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 8e36b53d395..31e3345761a 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -547,7 +547,7 @@ error: Variable cannot be reassigned from inflight --> ../../../examples/tests/invalid/class.w:61:5 | 61 | this.y = 1; - | ^^^^^^^^^^^ Variable cannot be reassigned from inflight + | ^^^^^^ Variable cannot be reassigned from inflight error: Expected type to be \\"num\\", but got \\"str\\" instead @@ -1327,7 +1327,7 @@ exports[`inflight_reassign.w 1`] = ` --> ../../../examples/tests/invalid/inflight_reassign.w:5:3 | 5 | xvar = \\"hi\\"; - | ^^^^^^^^^^^^ Variable cannot be reassigned from inflight + | ^^^^ Variable cannot be reassigned from inflight error: Variable is not reassignable From 3d378bb269954459b57265a22d6fdb77e46a0c78 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Mon, 11 Sep 2023 22:22:39 +0300 Subject: [PATCH 30/56] cr cleanup --- libs/wingc/src/type_check.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index e973656eedb..59ffe3663ae 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -4638,13 +4638,6 @@ impl<'a> TypeChecker<'a> { let mut property_variable = self.resolve_variable_from_instance_type(instance_type, property, env, object); - // Validate access modifier - // if !property_variable.type_.is_unresolved() { - // // TODO: this isn't good enough becaues `instance_type` might be an array so we need to "actual" class_type (Array). This is done for us in - // // `resolve_variable_from_instance_type`, fixing this might also make the unresolved check above redundant - // self.check_access(env, instance_type, property, property_variable.access_modifier); - // } - // if the object is `this`, then use the property's phase instead of the object phase let property_phase = if property_variable.phase == Phase::Independent { instance_phase From eec4ea861b6b9329518e1ebf479ba6961b4d6a36 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Mon, 11 Sep 2023 22:28:40 +0300 Subject: [PATCH 31/56] cr --- libs/wingc/src/type_check.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 59ffe3663ae..c8ba3289ed7 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -4862,7 +4862,7 @@ impl<'a> TypeChecker<'a> { let SymbolEnvKind::Type(property_defined_in) = lookup_info.env.kind else { panic!("Expected env to be a type env"); }; - // Check if the class in which the property is defined is the current class nesting + // Check if the class in which the property is defined is one of the classes we're currently nested in let mut private_access = false; let mut protected_access = false; for current_class in self.ctx.current_class_nesting() { From e36efd38f4d89ebed6e94762a0ea44f739220b3f Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Tue, 12 Sep 2023 10:25:46 +0300 Subject: [PATCH 32/56] cr fix: `super()` call type checked in place and not in class definition. --- libs/wingc/src/type_check.rs | 110 ++++++++++++--------- tools/hangar/__snapshots__/invalid.ts.snap | 22 ++--- 2 files changed, 74 insertions(+), 58 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index c8ba3289ed7..e509b8d2553 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -2399,7 +2399,7 @@ impl<'a> TypeChecker<'a> { &mut self, arg_list: &ArgList, func_sig: &FunctionSignature, - exp: &impl Spanned, + call_span: &impl Spanned, arg_list_types: ArgListTypes, ) -> Option { // Verify arity @@ -2410,7 +2410,7 @@ impl<'a> TypeChecker<'a> { "Expected {} positional argument(s) but got {}", min_args, pos_args_count ); - self.spanned_error(exp, err_text); + self.spanned_error(call_span, err_text); return Some(self.types.error()); } @@ -2419,19 +2419,22 @@ impl<'a> TypeChecker<'a> { Some(arg) => arg.typeref.maybe_unwrap_option(), None => { self.spanned_error( - exp, - format!("Expected 0 named arguments for func at {}", exp.span().to_string()), + call_span, + format!( + "Expected 0 named arguments for func at {}", + call_span.span().to_string() + ), ); return Some(self.types.error()); } }; if !last_arg.is_struct() { - self.spanned_error(exp, "No named arguments expected"); + self.spanned_error(call_span, "No named arguments expected"); return Some(self.types.error()); } - self.validate_structural_type(&arg_list_types.named_args, &last_arg, exp); + self.validate_structural_type(&arg_list_types.named_args, &last_arg, call_span); } // Count number of optional parameters from the end of the function's params @@ -2469,7 +2472,7 @@ impl<'a> TypeChecker<'a> { min_args, max_args, arg_count ) }; - self.spanned_error(exp, err_text); + self.spanned_error(call_span, err_text); } let params = func_sig.parameters.iter(); @@ -3052,7 +3055,7 @@ impl<'a> TypeChecker<'a> { println!("{}", env); } StmtKind::SuperConstructor { arg_list } => { - tc.type_check_arg_list(arg_list, env); + tc.type_check_super_constructor_against_parent_initializer(stmt, arg_list, env); } }); } @@ -3447,12 +3450,6 @@ impl<'a> TypeChecker<'a> { if let FunctionBody::Statements(scope) = &ast_class.inflight_initializer.body { self.check_class_field_initialization(&scope, &ast_class.fields, Phase::Inflight); - self.type_check_super_constructor_against_parent_initializer( - scope, - class_type, - &mut class_type.as_class_mut().unwrap().env, - CLASS_INFLIGHT_INIT_NAME, - ); }; // Type check constructor @@ -3466,13 +3463,6 @@ impl<'a> TypeChecker<'a> { self.check_class_field_initialization(&init_statements, &ast_class.fields, Phase::Preflight); - self.type_check_super_constructor_against_parent_initializer( - init_statements, - class_type, - &mut class_type.as_class_mut().unwrap().env, - CLASS_INIT_NAME, - ); - // Type check the inflight initializer self.type_check_method( class_type, @@ -3926,35 +3916,61 @@ impl<'a> TypeChecker<'a> { fn type_check_super_constructor_against_parent_initializer( &mut self, - scope: &Scope, - class_type: TypeRef, + super_constructor_call: &Stmt, + arg_list: &ArgList, env: &mut SymbolEnv, - init_name: &str, ) { - if scope.statements.len() >= 1 { - match &scope.statements[0].kind { - StmtKind::SuperConstructor { arg_list } => { - if let Some(parent_class) = &class_type.as_class().unwrap().parent { - let parent_initializer = parent_class - .as_class() - .unwrap() - .methods(false) - .filter(|(name, _type)| name == init_name) - .collect_vec()[0] - .1; - - let arg_list_types = self.type_check_arg_list(&arg_list, env); - self.type_check_arg_list_against_function_sig( - &arg_list, - parent_initializer.as_function_sig().unwrap(), - &scope.statements[0], - arg_list_types, - ); - } - } - _ => {} // No super no problem - } + let arg_list_types = self.type_check_arg_list(arg_list, env); + + // Verify we're inside a class + let class_type = if let Some(current_clas) = self.ctx.current_class().cloned() { + self + .resolve_user_defined_type(¤t_clas, env, self.ctx.current_stmt_idx()) + .expect("current class type to be defined") + } else { + self.spanned_error( + super_constructor_call, + "Call to super constructor can only be done from within a class initializer", + ); + return; + }; + + let init_name = if env.phase == Phase::Inflight { + CLASS_INFLIGHT_INIT_NAME + } else { + CLASS_INIT_NAME + }; + + // Verify we're inside the class's initializer + let (method_name, _) = self.ctx.current_method().expect("to be inside a method"); + if method_name.name != init_name { + self.spanned_error( + super_constructor_call, + "Call to super constructor can only be done from within a class initializer", + ); + return; + } + + // Verify the class has a parent class + let Some(parent_class) = &class_type.as_class().expect("class type to be a class").parent else { + self.spanned_error(super_constructor_call, format!("Class \"{class_type}\" does not have a parent class")); + return; }; + + let parent_initializer = parent_class + .as_class() + .unwrap() + .methods(false) + .filter(|(name, _type)| name == init_name) + .collect_vec()[0] + .1; + + self.type_check_arg_list_against_function_sig( + &arg_list, + parent_initializer.as_function_sig().unwrap(), + super_constructor_call, + arg_list_types, + ); } /// Validate if the fields of a class are initialized in the constructor (init) according to the given phase. diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 31e3345761a..0cfd02cab9e 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -515,17 +515,10 @@ error: Unknown symbol \\"C11\\" | ^^^ Unknown symbol \\"C11\\" -error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/class.w:123:11 - | -123 | super(someStr); - | ^^^^^^^ Expected type to be \\"num\\", but got \\"str\\" instead - - error: Expected 1 positional argument(s) but got 0 - --> ../../../examples/tests/invalid/class.w:132:5 + --> ../../../examples/tests/invalid/class.w:157:5 | -132 | super(); +157 | super(); | ^^^^^^^^ Expected 1 positional argument(s) but got 0 @@ -537,12 +530,19 @@ error: Expected 1 arguments but got 2 error: Expected 1 positional argument(s) but got 0 - --> ../../../examples/tests/invalid/class.w:157:5 + --> ../../../examples/tests/invalid/class.w:132:5 | -157 | super(); +132 | super(); | ^^^^^^^^ Expected 1 positional argument(s) but got 0 +error: Expected type to be \\"num\\", but got \\"str\\" instead + --> ../../../examples/tests/invalid/class.w:123:11 + | +123 | super(someStr); + | ^^^^^^^ Expected type to be \\"num\\", but got \\"str\\" instead + + error: Variable cannot be reassigned from inflight --> ../../../examples/tests/invalid/class.w:61:5 | From e82f9aafaf0ab777fe61d5c369005b74463fde96 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Tue, 12 Sep 2023 10:39:01 +0300 Subject: [PATCH 33/56] cr fix --- libs/wingc/src/type_check.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index e509b8d2553..64b74db7a9a 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -4896,14 +4896,17 @@ impl<'a> TypeChecker<'a> { match var.access_modifier { AccessModifier::Private => { if !private_access { - self.spanned_error(property, format!("Cannot access private member {property} of {class}")); + self.spanned_error( + property, + format!("Cannot access private member \"{property}\" of \"{class}\""), + ); } } AccessModifier::Protected => { if !protected_access { self.spanned_error( property, - format!("Cannot access protected member {property} of {class}"), + format!("Cannot access protected member \"{property}\" of \"{class}\""), ); } } From 86696cdbe15961b81f07ab5d4e5b06b0c33bfe5b Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Tue, 12 Sep 2023 10:54:12 +0300 Subject: [PATCH 34/56] cr fix: add multi level inheritence test for access_modifiers --- examples/tests/invalid/access_modifiers.w | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/examples/tests/invalid/access_modifiers.w b/examples/tests/invalid/access_modifiers.w index 5e8712985ae..a9226a1b648 100644 --- a/examples/tests/invalid/access_modifiers.w +++ b/examples/tests/invalid/access_modifiers.w @@ -59,6 +59,34 @@ class Bar extends Foo { } } +// Check 2nd level inheritance +class Baz extends Bar { + method() { + // Check protected access + log(this.protected_field); + log(this.private_field); + // ^ Cannot access private member + log(this.public_field); + this.public_method(); + this.protected_method(); + this.private_method(); + // ^ Cannot access private member + } + + static static_method() { + // Check static protected access + Foo.public_static_method(); + Foo.protected_static_method(); + Foo.private_static_method(); + // ^ Cannot access private member + // Check static protected access using parent class (in which the methods are not defined) + Bar.public_static_method(); + Bar.protected_static_method(); + Bar.private_static_method(); + // ^ Cannot access private member + } +} + let foo = new Foo(); // Chck access from non class log(foo.protected_field); From 6d93c6b7a94e968d5bb24357b4721488af1c6b0b Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Tue, 12 Sep 2023 08:09:05 +0000 Subject: [PATCH 35/56] chore: self mutation (build.diff) Signed-off-by: monada-bot[bot] --- .../fails_base_class_with_lifted_field_object_unqualified.snap | 2 +- libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap b/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap index e1a61bbbe0b..39c7cef06a2 100644 --- a/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap +++ b/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap @@ -2,5 +2,5 @@ source: libs/wingc/src/jsify/tests.rs --- ## Errors -Cannot access private member b of Derived 12:13 +Cannot access private member "b" of "Derived" 12:13 Cannot qualify access to a lifted object of type "Bucket" (see https://github.com/winglang/wing/issues/76 for more details) 12:8 diff --git a/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap b/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap index 353225a96a4..448f6bbbfbc 100644 --- a/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap +++ b/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap @@ -2,5 +2,5 @@ source: libs/wingc/src/jsify/tests.rs --- ## Errors -Cannot access private member staticMethod of MyType 6:17 +Cannot access private member "staticMethod" of "MyType" 6:17 Cannot call into preflight phase while inflight 6:10 From e1f162b7d32d00bed5aa915f49ad7dc48c1eedcd Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Tue, 12 Sep 2023 08:09:05 +0000 Subject: [PATCH 36/56] chore: self mutation (e2e-2of2.diff) Signed-off-by: monada-bot[bot] --- tools/hangar/__snapshots__/invalid.ts.snap | 194 ++++++++++++--------- 1 file changed, 111 insertions(+), 83 deletions(-) diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 0cfd02cab9e..2a66ad17648 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -16,95 +16,123 @@ Duration " `; exports[`access_modifiers.w 1`] = ` -"error: Cannot access protected member protected_field of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:64:9 +"error: Cannot access protected member \\"protected_field\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:92:9 | -64 | log(foo.protected_field); - | ^^^^^^^^^^^^^^^ Cannot access protected member protected_field of Foo +92 | log(foo.protected_field); + | ^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_field\\" of \\"Foo\\" -error: Cannot access private member private_field of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:66:9 +error: Cannot access private member \\"private_field\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:94:9 | -66 | log(foo.private_field); - | ^^^^^^^^^^^^^ Cannot access private member private_field of Foo +94 | log(foo.private_field); + | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Foo\\" -error: Cannot access protected member protected_static_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:70:5 +error: Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:98:5 | -70 | Foo.protected_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member protected_static_method of Foo +98 | Foo.protected_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" -error: Cannot access private member private_static_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:72:5 - | -72 | Foo.private_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member private_static_method of Foo +error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:100:5 + | +100 | Foo.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" -error: Cannot access protected member protected_static_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:92:9 - | -92 | Foo.protected_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member protected_static_method of Foo +error: Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:120:9 + | +120 | Foo.protected_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" -error: Cannot access private member private_static_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:94:9 - | -94 | Foo.private_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member private_static_method of Foo +error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:122:9 + | +122 | Foo.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" + + +error: Cannot access protected member \\"protected_field\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:106:13 + | +106 | log(foo.protected_field); + | ^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_field\\" of \\"Foo\\" + + +error: Cannot access private member \\"private_field\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:108:13 + | +108 | log(foo.private_field); + | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Foo\\" + + +error: Cannot access protected member \\"protected_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:112:9 + | +112 | foo.protected_method(); + | ^^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_method\\" of \\"Foo\\" + + +error: Cannot access private member \\"private_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:114:9 + | +114 | foo.private_method(); + | ^^^^^^^^^^^^^^ Cannot access private member \\"private_method\\" of \\"Foo\\" -error: Cannot access protected member protected_field of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:78:13 +error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:80:9 | -78 | log(foo.protected_field); - | ^^^^^^^^^^^^^^^ Cannot access protected member protected_field of Foo +80 | Foo.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" -error: Cannot access private member private_field of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:80:13 +error: Cannot access private member \\"private_static_method\\" of \\"Bar\\" + --> ../../../examples/tests/invalid/access_modifiers.w:85:9 | -80 | log(foo.private_field); - | ^^^^^^^^^^^^^ Cannot access private member private_field of Foo +85 | Bar.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Bar\\" -error: Cannot access protected member protected_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:84:9 +error: Cannot access private member \\"private_field\\" of \\"Baz\\" + --> ../../../examples/tests/invalid/access_modifiers.w:67:14 | -84 | foo.protected_method(); - | ^^^^^^^^^^^^^^^^ Cannot access protected member protected_method of Foo +67 | log(this.private_field); + | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Baz\\" -error: Cannot access private member private_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:86:9 +error: Cannot access private member \\"private_method\\" of \\"Baz\\" + --> ../../../examples/tests/invalid/access_modifiers.w:72:10 | -86 | foo.private_method(); - | ^^^^^^^^^^^^^^ Cannot access private member private_method of Foo +72 | this.private_method(); + | ^^^^^^^^^^^^^^ Cannot access private member \\"private_method\\" of \\"Baz\\" -error: Cannot access private member private_static_method of Foo +error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" --> ../../../examples/tests/invalid/access_modifiers.w:57:9 | 57 | Foo.private_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member private_static_method of Foo + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" -error: Cannot access private member private_field of Bar +error: Cannot access private member \\"private_field\\" of \\"Bar\\" --> ../../../examples/tests/invalid/access_modifiers.w:44:14 | 44 | log(this.private_field); - | ^^^^^^^^^^^^^ Cannot access private member private_field of Bar + | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Bar\\" -error: Cannot access private member private_method of Bar +error: Cannot access private member \\"private_method\\" of \\"Bar\\" --> ../../../examples/tests/invalid/access_modifiers.w:49:10 | 49 | this.private_method(); - | ^^^^^^^^^^^^^^ Cannot access private member private_method of Bar + | ^^^^^^^^^^^^^^ Cannot access private member \\"private_method\\" of \\"Bar\\" @@ -122,11 +150,11 @@ exports[`access_static_from_instance.w 1`] = ` | ^^^^^^^^^^^^^^ Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 -error: Cannot access private member f of Foo +error: Cannot access private member \\"f\\" of \\"Foo\\" --> ../../../examples/tests/invalid/access_static_from_instance.w:19:5 | 19 | foo.f; // Can't access static fields through instances - | ^ Cannot access private member f of Foo + | ^ Cannot access private member \\"f\\" of \\"Foo\\" error: Cannot access static property \\"f\\" from instance @@ -136,11 +164,11 @@ error: Cannot access static property \\"f\\" from instance | ^ Cannot access static property \\"f\\" from instance -error: Cannot access private member m of Foo +error: Cannot access private member \\"m\\" of \\"Foo\\" --> ../../../examples/tests/invalid/access_static_from_instance.w:20:5 | 20 | foo.m(); // Can't access static methods through instances - | ^ Cannot access private member m of Foo + | ^ Cannot access private member \\"m\\" of \\"Foo\\" error: Cannot access static property \\"m\\" from instance @@ -310,11 +338,11 @@ exports[`call_inflight_from_preflight.w 1`] = ` | ^^^^^^^^^^^^^^ Cannot call into inflight phase while preflight -error: Cannot access private member do of Foo +error: Cannot access private member \\"do\\" of \\"Foo\\" --> ../../../examples/tests/invalid/call_inflight_from_preflight.w:12:5 | 12 | foo.do(); - | ^^ Cannot access private member do of Foo + | ^^ Cannot access private member \\"do\\" of \\"Foo\\" error: Cannot call into inflight phase while preflight @@ -1345,46 +1373,46 @@ Duration " `; exports[`inflight_ref_explicit_ops.w 1`] = ` -"error: Cannot access private member test4 of Test +"error: Cannot access private member \\"test4\\" of \\"Test\\" --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:60:18 | 60 | test \\"test4\\" { f.test4(); } - | ^^^^^ Cannot access private member test4 of Test + | ^^^^^ Cannot access private member \\"test4\\" of \\"Test\\" -error: Cannot access private member test3 of Test +error: Cannot access private member \\"test3\\" of \\"Test\\" --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:59:18 | 59 | test \\"test3\\" { f.test3(); } - | ^^^^^ Cannot access private member test3 of Test + | ^^^^^ Cannot access private member \\"test3\\" of \\"Test\\" -error: Cannot access private member test2 of Test +error: Cannot access private member \\"test2\\" of \\"Test\\" --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:58:18 | 58 | test \\"test2\\" { f.test2(); } - | ^^^^^ Cannot access private member test2 of Test + | ^^^^^ Cannot access private member \\"test2\\" of \\"Test\\" -error: Cannot access private member test1 of Test +error: Cannot access private member \\"test1\\" of \\"Test\\" --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:57:18 | 57 | test \\"test1\\" { f.test1(); } - | ^^^^^ Cannot access private member test1 of Test + | ^^^^^ Cannot access private member \\"test1\\" of \\"Test\\" -error: Cannot access private member anotherStr of Another +error: Cannot access private member \\"anotherStr\\" of \\"Another\\" --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:52:25 | 52 | assert(this.another.anotherStr == \\"bang\\"); - | ^^^^^^^^^^ Cannot access private member anotherStr of Another + | ^^^^^^^^^^ Cannot access private member \\"anotherStr\\" of \\"Another\\" -error: Cannot access private member inflightReturnsResource of Another +error: Cannot access private member \\"inflightReturnsResource\\" of \\"Another\\" --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:42:26 | 42 | let q = this.another.inflightReturnsResource(); - | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member inflightReturnsResource of Another + | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"inflightReturnsResource\\" of \\"Another\\" error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) @@ -1416,25 +1444,25 @@ Duration " `; exports[`inflight_ref_resource_sub_method.w 1`] = ` -"error: Cannot access private member test of Test +"error: Cannot access private member \\"test\\" of \\"Test\\" --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:40:17 | 40 | test \\"test\\" { f.test(); } - | ^^^^ Cannot access private member test of Test + | ^^^^ Cannot access private member \\"test\\" of \\"Test\\" -error: Cannot access private member inflightReturnsResource of Another +error: Cannot access private member \\"inflightReturnsResource\\" of \\"Another\\" --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:31:26 | 31 | let q = this.another.inflightReturnsResource(); - | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member inflightReturnsResource of Another + | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"inflightReturnsResource\\" of \\"Another\\" -error: Cannot access private member inflightReturnsResource2 of Another +error: Cannot access private member \\"inflightReturnsResource2\\" of \\"Another\\" --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:34:27 | 34 | let q2 = this.another.inflightReturnsResource2(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member inflightReturnsResource2 of Another + | ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"inflightReturnsResource2\\" of \\"Another\\" error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) @@ -1459,11 +1487,11 @@ Duration " `; exports[`inflight_ref_unknown_op.w 1`] = ` -"error: Cannot access private member test of Test +"error: Cannot access private member \\"test\\" of \\"Test\\" --> ../../../examples/tests/invalid/inflight_ref_unknown_op.w:24:17 | 24 | test \\"test\\" { f.test(); } - | ^^^^ Cannot access private member test of Test + | ^^^^ Cannot access private member \\"test\\" of \\"Test\\" error: Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) @@ -1876,11 +1904,11 @@ error: Cannot assign nil value to variables without explicit optional type | ^^^^^^^^^^^^^^^ Cannot assign nil value to variables without explicit optional type -error: Cannot access private member setBar of Foo +error: Cannot access private member \\"setBar\\" of \\"Foo\\" --> ../../../examples/tests/invalid/nil.w:20:7 | 20 | foo.setBar(nil); - | ^^^^^^ Cannot access private member setBar of Foo + | ^^^^^^ Cannot access private member \\"setBar\\" of \\"Foo\\" error: Expected type to be \\"num\\", but got \\"nil\\" instead (hint: to allow \\"nil\\" assignment use optional type: \\"num?\\") @@ -2014,11 +2042,11 @@ Duration " exports[`panic.w 2`] = `"Panicked, backtrace not captured: Unsupported"`; exports[`preflight_from_inflight.w 1`] = ` -"error: Cannot access private member myPreflight of MyResource +"error: Cannot access private member \\"myPreflight\\" of \\"MyResource\\" --> ../../../examples/tests/invalid/preflight_from_inflight.w:15:12 | 15 | this.r.myPreflight(); - | ^^^^^^^^^^^ Cannot access private member myPreflight of MyResource + | ^^^^^^^^^^^ Cannot access private member \\"myPreflight\\" of \\"MyResource\\" error: Cannot call into preflight phase while inflight @@ -2100,11 +2128,11 @@ error: Variable is not reassignable | ^^^^^^ Variable is not reassignable -error: Cannot access private member inner of InnerR +error: Cannot access private member \\"inner\\" of \\"InnerR\\" --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:30:17 | 30 | this.innerR.inner = 2; - | ^^^^^ Cannot access private member inner of InnerR + | ^^^^^ Cannot access private member \\"inner\\" of \\"InnerR\\" error: Variable is not reassignable @@ -2122,11 +2150,11 @@ Duration " `; exports[`resource_access_field_as_method.w 1`] = ` -"error: Cannot access private member name of SomeResource +"error: Cannot access private member \\"name\\" of \\"SomeResource\\" --> ../../../examples/tests/invalid/resource_access_field_as_method.w:9:3 | 9 | x.name(); - | ^^^^ Cannot access private member name of SomeResource + | ^^^^ Cannot access private member \\"name\\" of \\"SomeResource\\" error: Expected a function or method, found \\"str\\" From d3d1c3c33f35fb43ed570f2881d5b8782821d5fa Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Tue, 12 Sep 2023 12:29:19 +0300 Subject: [PATCH 37/56] cr fix: interfaces must be public --- examples/tests/invalid/access_modifiers.w | 10 +- .../invalid/access_static_from_instance.w | 4 +- .../invalid/call_inflight_from_preflight.w | 2 +- examples/tests/invalid/impl_interface.w | 2 +- ...flight_class_interface_structural_typing.w | 2 +- .../tests/invalid/inflight_ref_explicit_ops.w | 12 +- .../inflight_ref_resource_sub_method.w | 6 +- .../tests/invalid/inflight_ref_unknown_op.w | 2 +- examples/tests/invalid/nil.w | 2 +- .../tests/invalid/preflight_from_inflight.w | 2 +- .../invalid/reassign_to_nonreassignable.w | 2 +- .../invalid/resource_access_field_as_method.w | 2 +- examples/tests/valid/bring_local.w | 2 +- examples/tests/valid/impl_interface.w | 10 +- ...flight_class_structural_interace_handler.w | 2 +- .../valid/resource_as_inflight_literal.w | 2 +- .../tests/valid/resource_captures_globals.w | 2 +- ..._with_lifted_field_object_unqualified.snap | 2 +- .../snapshots/fails_on_preflight_static.snap | 2 +- libs/wingc/src/type_check.rs | 31 +- tools/hangar/__snapshots__/invalid.ts.snap | 274 +++++++----------- 21 files changed, 157 insertions(+), 218 deletions(-) diff --git a/examples/tests/invalid/access_modifiers.w b/examples/tests/invalid/access_modifiers.w index a9226a1b648..ff49475a0e7 100644 --- a/examples/tests/invalid/access_modifiers.w +++ b/examples/tests/invalid/access_modifiers.w @@ -1,4 +1,10 @@ -class Foo { +interface SomeInterface { + public_method(): void; + protected_method(): void; + private_method(): void; +} + +class Foo impl SomeInterface { protected protected_field: str; private_field: str; public public_field: str; @@ -30,7 +36,9 @@ class Foo { public public_method() {} protected protected_method() {} + // ^ Method is not public but it's part of an interface private_method() {} + //^ Method is not public but it's part of an interface public static public_static_method() {} protected static protected_static_method() {} diff --git a/examples/tests/invalid/access_static_from_instance.w b/examples/tests/invalid/access_static_from_instance.w index e12b91b56ca..82916dc4b4d 100644 --- a/examples/tests/invalid/access_static_from_instance.w +++ b/examples/tests/invalid/access_static_from_instance.w @@ -1,9 +1,9 @@ class Foo { instanceField: num; - static f: num; + public static f: num; - static m() { + public static m() { this.instanceField = 1; // Can't access instance fields from static methods this.f = 1; // Can't access static fields through `this` } diff --git a/examples/tests/invalid/call_inflight_from_preflight.w b/examples/tests/invalid/call_inflight_from_preflight.w index 0a385ddb614..f42b8c14227 100644 --- a/examples/tests/invalid/call_inflight_from_preflight.w +++ b/examples/tests/invalid/call_inflight_from_preflight.w @@ -5,7 +5,7 @@ util.sleep(1s); //^^^^^^^^^^^^^^ Cannot call into inflight phase while preflight class Foo { - inflight do() {} + public inflight do() {} } let foo = new Foo(); // Call an inflight method diff --git a/examples/tests/invalid/impl_interface.w b/examples/tests/invalid/impl_interface.w index 05012fec881..e5100ed76b1 100644 --- a/examples/tests/invalid/impl_interface.w +++ b/examples/tests/invalid/impl_interface.w @@ -5,7 +5,7 @@ class A impl cloud.IQueueSetConsumerHandler { } class B impl cloud.IQueueSetConsumerHandler { - inflight handle(x: num) { + public inflight handle(x: num) { // Error: Expected type to be "inflight (str): void", but got "inflight (num): void" instead return; } diff --git a/examples/tests/invalid/inflight_class_interface_structural_typing.w b/examples/tests/invalid/inflight_class_interface_structural_typing.w index 0c45c952c42..9f35f92ad0c 100644 --- a/examples/tests/invalid/inflight_class_interface_structural_typing.w +++ b/examples/tests/invalid/inflight_class_interface_structural_typing.w @@ -13,7 +13,7 @@ inflight class NotGoo { test "f" { inflight class YesGoo impl IGoo { - notHandle(): void { + public notHandle(): void { log("i am goo"); } } diff --git a/examples/tests/invalid/inflight_ref_explicit_ops.w b/examples/tests/invalid/inflight_ref_explicit_ops.w index beb54b518e2..065a55454ac 100644 --- a/examples/tests/invalid/inflight_ref_explicit_ops.w +++ b/examples/tests/invalid/inflight_ref_explicit_ops.w @@ -2,14 +2,14 @@ bring cloud; class Another { myQueue: cloud.Queue; - anotherStr: str; + public anotherStr: str; init () { this.myQueue = new cloud.Queue(); this.anotherStr = "bang"; } - inflight inflightReturnsResource(): cloud.Queue { + public inflight inflightReturnsResource(): cloud.Queue { return this.myQueue; // ^^^^^^^^ Cannot qualify access to a lifted object } @@ -30,7 +30,7 @@ class Test { this.justStr = "hello"; } - inflight test1() { + public inflight test1() { let x = this.b; // ^ Cannot qualify access to a lifted object x.put("hello", "world"); @@ -38,17 +38,17 @@ class Test { this.justBucket.put("hello", "world"); } - inflight test2() { + public inflight test2() { let q = this.another.inflightReturnsResource(); q.push("push!"); } - inflight test3() { + public inflight test3() { let b = this.array.at(1); assert(b.list().length == 0); } - inflight test4() { + public inflight test4() { assert(this.another.anotherStr == "bang"); } } diff --git a/examples/tests/invalid/inflight_ref_resource_sub_method.w b/examples/tests/invalid/inflight_ref_resource_sub_method.w index 7722e57194d..923c0096b50 100644 --- a/examples/tests/invalid/inflight_ref_resource_sub_method.w +++ b/examples/tests/invalid/inflight_ref_resource_sub_method.w @@ -9,12 +9,12 @@ class Another { this.myQueue = new cloud.Queue(); } - inflight inflightReturnsResource(): cloud.Queue { + public inflight inflightReturnsResource(): cloud.Queue { return this.myQueue; // ^^^^^^^^ Cannot qualify access to a lifted object } - inflight inflightReturnsResource2(): cloud.Queue { + public inflight inflightReturnsResource2(): cloud.Queue { return globalQueue; // ^^^^^^^^^^^^ Cannot qualify access to a lifted object } @@ -27,7 +27,7 @@ class Test { this.another = new Another(); } - inflight test() { + public inflight test() { let q = this.another.inflightReturnsResource(); q.push("push!"); diff --git a/examples/tests/invalid/inflight_ref_unknown_op.w b/examples/tests/invalid/inflight_ref_unknown_op.w index c981024a9d1..c09371ebbe6 100644 --- a/examples/tests/invalid/inflight_ref_unknown_op.w +++ b/examples/tests/invalid/inflight_ref_unknown_op.w @@ -9,7 +9,7 @@ class Test { this.b = new cloud.Bucket(); } - inflight test() { + public inflight test() { let x = this.b; // ^ Cannot qualify which operations are performed on object x.put("hello", "world"); diff --git a/examples/tests/invalid/nil.w b/examples/tests/invalid/nil.w index 235d80a6d84..c292a762a52 100644 --- a/examples/tests/invalid/nil.w +++ b/examples/tests/invalid/nil.w @@ -9,7 +9,7 @@ class Foo { this.bar = 1; } - inflight setBar(b: num) { + public inflight setBar(b: num) { this.bar = b; } } diff --git a/examples/tests/invalid/preflight_from_inflight.w b/examples/tests/invalid/preflight_from_inflight.w index 59e1babca86..cdd60a2c6c1 100644 --- a/examples/tests/invalid/preflight_from_inflight.w +++ b/examples/tests/invalid/preflight_from_inflight.w @@ -1,7 +1,7 @@ bring cloud; class MyResource { - myPreflight() { } + public myPreflight() { } } class Test { diff --git a/examples/tests/invalid/reassign_to_nonreassignable.w b/examples/tests/invalid/reassign_to_nonreassignable.w index 748066a2932..70f291092dd 100644 --- a/examples/tests/invalid/reassign_to_nonreassignable.w +++ b/examples/tests/invalid/reassign_to_nonreassignable.w @@ -3,7 +3,7 @@ let x = 5; x = x + 1; class InnerR { - inflight inner: num; + public inflight inner: num; inflight init() { this.inner = 1; } diff --git a/examples/tests/invalid/resource_access_field_as_method.w b/examples/tests/invalid/resource_access_field_as_method.w index d313e1b6ed3..b56be62be9c 100644 --- a/examples/tests/invalid/resource_access_field_as_method.w +++ b/examples/tests/invalid/resource_access_field_as_method.w @@ -1,5 +1,5 @@ class SomeResource { - name: str; + public name: str; init() { this.name = "John Doe"; } diff --git a/examples/tests/valid/bring_local.w b/examples/tests/valid/bring_local.w index cfa77a75442..03a12ad0074 100644 --- a/examples/tests/valid/bring_local.w +++ b/examples/tests/valid/bring_local.w @@ -23,7 +23,7 @@ assert(c != file1.Color.RED); // interfaces from other files can be used class Triangle impl file1.Shape { - area(): num { + public area(): num { return 1; } } diff --git a/examples/tests/valid/impl_interface.w b/examples/tests/valid/impl_interface.w index 5776ed36aa6..0961ce6d6a2 100644 --- a/examples/tests/valid/impl_interface.w +++ b/examples/tests/valid/impl_interface.w @@ -1,7 +1,7 @@ bring cloud; class A impl cloud.IQueueSetConsumerHandler { - inflight handle(msg: str) { + public inflight handle(msg: str) { return; } } @@ -25,13 +25,13 @@ interface I3 extends I2 { } class r impl I3 { - method1(x: num): num { + public method1(x: num): num { return x; } - inflight method2(x: str): str { + public inflight method2(x: str): str { return x; } - method3(x: Array): Array { + public method3(x: Array): Array { return x; } } @@ -42,7 +42,7 @@ interface IAnimal { } class Dog impl IAnimal { - inflight eat() { + public inflight eat() { return; } } diff --git a/examples/tests/valid/inflight_class_structural_interace_handler.w b/examples/tests/valid/inflight_class_structural_interace_handler.w index 6d62e2adf12..d3ccf36a872 100644 --- a/examples/tests/valid/inflight_class_structural_interace_handler.w +++ b/examples/tests/valid/inflight_class_structural_interace_handler.w @@ -12,7 +12,7 @@ inflight class NotGoo { test "structure interface types for 'handle'" { inflight class YesGoo impl IGoo { - handle(): num { + public handle(): num { return 456; } diff --git a/examples/tests/valid/resource_as_inflight_literal.w b/examples/tests/valid/resource_as_inflight_literal.w index 148dd23caf5..905f3d44222 100644 --- a/examples/tests/valid/resource_as_inflight_literal.w +++ b/examples/tests/valid/resource_as_inflight_literal.w @@ -1,7 +1,7 @@ bring cloud; class Foo impl cloud.IFunctionHandler { - inflight handle(message: str): str { + public inflight handle(message: str): str { return "hello world!"; } } diff --git a/examples/tests/valid/resource_captures_globals.w b/examples/tests/valid/resource_captures_globals.w index ed0b2674ec7..56343924089 100644 --- a/examples/tests/valid/resource_captures_globals.w +++ b/examples/tests/valid/resource_captures_globals.w @@ -51,7 +51,7 @@ class MyResource { let $parentThis = this; class R impl cloud.ITopicOnMessageHandler { - inflight handle() { + public inflight handle() { globalCounter.inc(); $parentThis.localCounter.inc(); } diff --git a/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap b/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap index e1a61bbbe0b..39c7cef06a2 100644 --- a/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap +++ b/libs/wingc/src/jsify/snapshots/fails_base_class_with_lifted_field_object_unqualified.snap @@ -2,5 +2,5 @@ source: libs/wingc/src/jsify/tests.rs --- ## Errors -Cannot access private member b of Derived 12:13 +Cannot access private member "b" of "Derived" 12:13 Cannot qualify access to a lifted object of type "Bucket" (see https://github.com/winglang/wing/issues/76 for more details) 12:8 diff --git a/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap b/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap index 353225a96a4..448f6bbbfbc 100644 --- a/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap +++ b/libs/wingc/src/jsify/snapshots/fails_on_preflight_static.snap @@ -2,5 +2,5 @@ source: libs/wingc/src/jsify/tests.rs --- ## Errors -Cannot access private member staticMethod of MyType 6:17 +Cannot access private member "staticMethod" of "MyType" 6:17 Cannot call into preflight phase while inflight 6:10 diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 64b74db7a9a..cb061d4a412 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -3498,8 +3498,16 @@ impl<'a> TypeChecker<'a> { .env .lookup(&method_name.as_str().into(), None) { - let class_method_type = symbol.as_variable().expect("Expected method to be a variable").type_; + let class_method_var = symbol.as_variable().expect("Expected method to be a variable"); + let class_method_type = class_method_var.type_; self.validate_type(class_method_type, method_type, &ast_class.name); + // Make sure the method is public (interface methods must be public) + if !matches!(class_method_var.access_modifier, AccessModifier::Public) { + self.spanned_error( + &class_method_var.name, + format!("Method \"{method_name}\" is not public but it's part of the \"{interface_type}\" interface",), + ); + } } else { self.spanned_error( &ast_class.name, @@ -3510,27 +3518,6 @@ impl<'a> TypeChecker<'a> { ); } } - - // Check all fields are implemented - for (field_name, field_type) in interface_type.fields(true) { - if let Some(symbol) = &mut class_type - .as_class_mut() - .unwrap() - .env - .lookup(&field_name.as_str().into(), None) - { - let class_field_type = symbol.as_variable().expect("Expected field to be a variable").type_; - self.validate_type(class_field_type, field_type, &ast_class.name); - } else { - self.spanned_error( - &ast_class.name, - format!( - "Class \"{}\" does not implement field \"{}\" of interface \"{}\"", - &ast_class.name, field_name, interface_type.name.name - ), - ); - } - } } self.ctx.pop_class(); } diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 0cfd02cab9e..4ed6fd4755d 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -16,95 +16,137 @@ Duration " `; exports[`access_modifiers.w 1`] = ` -"error: Cannot access protected member protected_field of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:64:9 +"error: Method \\"private_method\\" is not public but it's part of the \\"SomeInterface\\" interface + --> ../../../examples/tests/invalid/access_modifiers.w:40:3 | -64 | log(foo.protected_field); - | ^^^^^^^^^^^^^^^ Cannot access protected member protected_field of Foo +40 | private_method() {} + | ^^^^^^^^^^^^^^ Method \\"private_method\\" is not public but it's part of the \\"SomeInterface\\" interface -error: Cannot access private member private_field of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:66:9 +error: Method \\"protected_method\\" is not public but it's part of the \\"SomeInterface\\" interface + --> ../../../examples/tests/invalid/access_modifiers.w:38:13 | -66 | log(foo.private_field); - | ^^^^^^^^^^^^^ Cannot access private member private_field of Foo +38 | protected protected_method() {} + | ^^^^^^^^^^^^^^^^ Method \\"protected_method\\" is not public but it's part of the \\"SomeInterface\\" interface -error: Cannot access protected member protected_static_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:70:5 - | -70 | Foo.protected_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member protected_static_method of Foo +error: Cannot access protected member \\"protected_field\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:100:9 + | +100 | log(foo.protected_field); + | ^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_field\\" of \\"Foo\\" -error: Cannot access private member private_static_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:72:5 - | -72 | Foo.private_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member private_static_method of Foo +error: Cannot access private member \\"private_field\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:102:9 + | +102 | log(foo.private_field); + | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Foo\\" -error: Cannot access protected member protected_static_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:92:9 - | -92 | Foo.protected_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member protected_static_method of Foo +error: Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:106:5 + | +106 | Foo.protected_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" -error: Cannot access private member private_static_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:94:9 - | -94 | Foo.private_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member private_static_method of Foo +error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:108:5 + | +108 | Foo.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" + + +error: Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:128:9 + | +128 | Foo.protected_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" + + +error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:130:9 + | +130 | Foo.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" + + +error: Cannot access protected member \\"protected_field\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:114:13 + | +114 | log(foo.protected_field); + | ^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_field\\" of \\"Foo\\" + + +error: Cannot access private member \\"private_field\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:116:13 + | +116 | log(foo.private_field); + | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Foo\\" + + +error: Cannot access protected member \\"protected_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:120:9 + | +120 | foo.protected_method(); + | ^^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_method\\" of \\"Foo\\" + + +error: Cannot access private member \\"private_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:122:9 + | +122 | foo.private_method(); + | ^^^^^^^^^^^^^^ Cannot access private member \\"private_method\\" of \\"Foo\\" -error: Cannot access protected member protected_field of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:78:13 +error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:88:9 | -78 | log(foo.protected_field); - | ^^^^^^^^^^^^^^^ Cannot access protected member protected_field of Foo +88 | Foo.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" -error: Cannot access private member private_field of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:80:13 +error: Cannot access private member \\"private_static_method\\" of \\"Bar\\" + --> ../../../examples/tests/invalid/access_modifiers.w:93:9 | -80 | log(foo.private_field); - | ^^^^^^^^^^^^^ Cannot access private member private_field of Foo +93 | Bar.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Bar\\" -error: Cannot access protected member protected_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:84:9 +error: Cannot access private member \\"private_field\\" of \\"Baz\\" + --> ../../../examples/tests/invalid/access_modifiers.w:75:14 | -84 | foo.protected_method(); - | ^^^^^^^^^^^^^^^^ Cannot access protected member protected_method of Foo +75 | log(this.private_field); + | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Baz\\" -error: Cannot access private member private_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:86:9 +error: Cannot access private member \\"private_method\\" of \\"Baz\\" + --> ../../../examples/tests/invalid/access_modifiers.w:80:10 | -86 | foo.private_method(); - | ^^^^^^^^^^^^^^ Cannot access private member private_method of Foo +80 | this.private_method(); + | ^^^^^^^^^^^^^^ Cannot access private member \\"private_method\\" of \\"Baz\\" -error: Cannot access private member private_static_method of Foo - --> ../../../examples/tests/invalid/access_modifiers.w:57:9 +error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:65:9 | -57 | Foo.private_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member private_static_method of Foo +65 | Foo.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" -error: Cannot access private member private_field of Bar - --> ../../../examples/tests/invalid/access_modifiers.w:44:14 +error: Cannot access private member \\"private_field\\" of \\"Bar\\" + --> ../../../examples/tests/invalid/access_modifiers.w:52:14 | -44 | log(this.private_field); - | ^^^^^^^^^^^^^ Cannot access private member private_field of Bar +52 | log(this.private_field); + | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Bar\\" -error: Cannot access private member private_method of Bar - --> ../../../examples/tests/invalid/access_modifiers.w:49:10 +error: Cannot access private member \\"private_method\\" of \\"Bar\\" + --> ../../../examples/tests/invalid/access_modifiers.w:57:10 | -49 | this.private_method(); - | ^^^^^^^^^^^^^^ Cannot access private member private_method of Bar +57 | this.private_method(); + | ^^^^^^^^^^^^^^ Cannot access private member \\"private_method\\" of \\"Bar\\" @@ -122,11 +164,11 @@ exports[`access_static_from_instance.w 1`] = ` | ^^^^^^^^^^^^^^ Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 -error: Cannot access private member f of Foo +error: Cannot access private member \\"f\\" of \\"Foo\\" --> ../../../examples/tests/invalid/access_static_from_instance.w:19:5 | 19 | foo.f; // Can't access static fields through instances - | ^ Cannot access private member f of Foo + | ^ Cannot access private member \\"f\\" of \\"Foo\\" error: Cannot access static property \\"f\\" from instance @@ -136,11 +178,11 @@ error: Cannot access static property \\"f\\" from instance | ^ Cannot access static property \\"f\\" from instance -error: Cannot access private member m of Foo +error: Cannot access private member \\"m\\" of \\"Foo\\" --> ../../../examples/tests/invalid/access_static_from_instance.w:20:5 | 20 | foo.m(); // Can't access static methods through instances - | ^ Cannot access private member m of Foo + | ^ Cannot access private member \\"m\\" of \\"Foo\\" error: Cannot access static property \\"m\\" from instance @@ -310,11 +352,11 @@ exports[`call_inflight_from_preflight.w 1`] = ` | ^^^^^^^^^^^^^^ Cannot call into inflight phase while preflight -error: Cannot access private member do of Foo +error: Cannot access private member \\"do\\" of \\"Foo\\" --> ../../../examples/tests/invalid/call_inflight_from_preflight.w:12:5 | 12 | foo.do(); - | ^^ Cannot access private member do of Foo + | ^^ Cannot access private member \\"do\\" of \\"Foo\\" error: Cannot call into inflight phase while preflight @@ -1345,49 +1387,7 @@ Duration " `; exports[`inflight_ref_explicit_ops.w 1`] = ` -"error: Cannot access private member test4 of Test - --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:60:18 - | -60 | test \\"test4\\" { f.test4(); } - | ^^^^^ Cannot access private member test4 of Test - - -error: Cannot access private member test3 of Test - --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:59:18 - | -59 | test \\"test3\\" { f.test3(); } - | ^^^^^ Cannot access private member test3 of Test - - -error: Cannot access private member test2 of Test - --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:58:18 - | -58 | test \\"test2\\" { f.test2(); } - | ^^^^^ Cannot access private member test2 of Test - - -error: Cannot access private member test1 of Test - --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:57:18 - | -57 | test \\"test1\\" { f.test1(); } - | ^^^^^ Cannot access private member test1 of Test - - -error: Cannot access private member anotherStr of Another - --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:52:25 - | -52 | assert(this.another.anotherStr == \\"bang\\"); - | ^^^^^^^^^^ Cannot access private member anotherStr of Another - - -error: Cannot access private member inflightReturnsResource of Another - --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:42:26 - | -42 | let q = this.another.inflightReturnsResource(); - | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member inflightReturnsResource of Another - - -error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) +"error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:13:12 | 13 | return this.myQueue; @@ -1416,28 +1416,7 @@ Duration " `; exports[`inflight_ref_resource_sub_method.w 1`] = ` -"error: Cannot access private member test of Test - --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:40:17 - | -40 | test \\"test\\" { f.test(); } - | ^^^^ Cannot access private member test of Test - - -error: Cannot access private member inflightReturnsResource of Another - --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:31:26 - | -31 | let q = this.another.inflightReturnsResource(); - | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member inflightReturnsResource of Another - - -error: Cannot access private member inflightReturnsResource2 of Another - --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:34:27 - | -34 | let q2 = this.another.inflightReturnsResource2(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access private member inflightReturnsResource2 of Another - - -error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) +"error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:13:12 | 13 | return this.myQueue; @@ -1459,14 +1438,7 @@ Duration " `; exports[`inflight_ref_unknown_op.w 1`] = ` -"error: Cannot access private member test of Test - --> ../../../examples/tests/invalid/inflight_ref_unknown_op.w:24:17 - | -24 | test \\"test\\" { f.test(); } - | ^^^^ Cannot access private member test of Test - - -error: Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) +"error: Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) --> ../../../examples/tests/invalid/inflight_ref_unknown_op.w:13:13 | 13 | let x = this.b; @@ -1876,13 +1848,6 @@ error: Cannot assign nil value to variables without explicit optional type | ^^^^^^^^^^^^^^^ Cannot assign nil value to variables without explicit optional type -error: Cannot access private member setBar of Foo - --> ../../../examples/tests/invalid/nil.w:20:7 - | -20 | foo.setBar(nil); - | ^^^^^^ Cannot access private member setBar of Foo - - error: Expected type to be \\"num\\", but got \\"nil\\" instead (hint: to allow \\"nil\\" assignment use optional type: \\"num?\\") --> ../../../examples/tests/invalid/nil.w:20:14 | @@ -2014,14 +1979,7 @@ Duration " exports[`panic.w 2`] = `"Panicked, backtrace not captured: Unsupported"`; exports[`preflight_from_inflight.w 1`] = ` -"error: Cannot access private member myPreflight of MyResource - --> ../../../examples/tests/invalid/preflight_from_inflight.w:15:12 - | -15 | this.r.myPreflight(); - | ^^^^^^^^^^^ Cannot access private member myPreflight of MyResource - - -error: Cannot call into preflight phase while inflight +"error: Cannot call into preflight phase while inflight --> ../../../examples/tests/invalid/preflight_from_inflight.w:15:5 | 15 | this.r.myPreflight(); @@ -2100,13 +2058,6 @@ error: Variable is not reassignable | ^^^^^^ Variable is not reassignable -error: Cannot access private member inner of InnerR - --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:30:17 - | -30 | this.innerR.inner = 2; - | ^^^^^ Cannot access private member inner of InnerR - - error: Variable is not reassignable --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:30:5 | @@ -2122,14 +2073,7 @@ Duration " `; exports[`resource_access_field_as_method.w 1`] = ` -"error: Cannot access private member name of SomeResource - --> ../../../examples/tests/invalid/resource_access_field_as_method.w:9:3 - | -9 | x.name(); - | ^^^^ Cannot access private member name of SomeResource - - -error: Expected a function or method, found \\"str\\" +"error: Expected a function or method, found \\"str\\" --> ../../../examples/tests/invalid/resource_access_field_as_method.w:9:1 | 9 | x.name(); From 9c94c74b5d34229ce650d0b3514f392b1f066e44 Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Tue, 12 Sep 2023 09:49:46 +0000 Subject: [PATCH 38/56] chore: self mutation (e2e-2of2.diff) Signed-off-by: monada-bot[bot] --- tools/hangar/__snapshots__/invalid.ts.snap | 25 ++-------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 4ed6fd4755d..6c6419f7b9e 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -160,15 +160,8 @@ exports[`access_static_from_instance.w 1`] = ` "error: Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 --> ../../../examples/tests/invalid/access_static_from_instance.w:4:3 | -4 | static f: num; - | ^^^^^^^^^^^^^^ Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 - - -error: Cannot access private member \\"f\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_static_from_instance.w:19:5 - | -19 | foo.f; // Can't access static fields through instances - | ^ Cannot access private member \\"f\\" of \\"Foo\\" +4 | public static f: num; + | ^^^^^^^^^^^^^^^^^^^^^ Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 error: Cannot access static property \\"f\\" from instance @@ -178,13 +171,6 @@ error: Cannot access static property \\"f\\" from instance | ^ Cannot access static property \\"f\\" from instance -error: Cannot access private member \\"m\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_static_from_instance.w:20:5 - | -20 | foo.m(); // Can't access static methods through instances - | ^ Cannot access private member \\"m\\" of \\"Foo\\" - - error: Cannot access static property \\"m\\" from instance --> ../../../examples/tests/invalid/access_static_from_instance.w:20:5 | @@ -352,13 +338,6 @@ exports[`call_inflight_from_preflight.w 1`] = ` | ^^^^^^^^^^^^^^ Cannot call into inflight phase while preflight -error: Cannot access private member \\"do\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/call_inflight_from_preflight.w:12:5 - | -12 | foo.do(); - | ^^ Cannot access private member \\"do\\" of \\"Foo\\" - - error: Cannot call into inflight phase while preflight --> ../../../examples/tests/invalid/call_inflight_from_preflight.w:12:1 | From 37ca5c3742a30395a848ffb085f37d98b129a403 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Tue, 12 Sep 2023 14:23:33 +0300 Subject: [PATCH 39/56] cr: `internal` not supported yet --- libs/tree-sitter-wing/grammar.js | 2 +- .../test/corpus/statements/class_and_resource.txt | 5 +++++ libs/wingc/src/parser.rs | 5 +++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libs/tree-sitter-wing/grammar.js b/libs/tree-sitter-wing/grammar.js index c956889d632..899d2128cd2 100644 --- a/libs/tree-sitter-wing/grammar.js +++ b/libs/tree-sitter-wing/grammar.js @@ -532,7 +532,7 @@ module.exports = grammar({ async_modifier: ($) => "async", - access_modifier: ($) => choice("public", "protected"), + access_modifier: ($) => choice("public", "protected", "internal"), variadic: ($) => "...", diff --git a/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt b/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt index 9b98a2ea497..13f86020f9a 100644 --- a/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt +++ b/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt @@ -79,6 +79,7 @@ class A { public inflight inflight_func2(): num {} protected inflight inflight_func3(): num {} pf_member: str; + internal internal_member: str; inflight if_member: str; public inflight var if_member2: str; protected inflight var if_member3: str; @@ -135,6 +136,10 @@ class A { (class_field name: (identifier) type: (builtin_type)) + (class_field + access_modifier: (access_modifier) + name: (identifier) + type: (builtin_type)) (class_field phase_modifier: (inflight_specifier) name: (identifier) diff --git a/libs/wingc/src/parser.rs b/libs/wingc/src/parser.rs index 2461143b6d4..7bcff315acb 100644 --- a/libs/wingc/src/parser.rs +++ b/libs/wingc/src/parser.rs @@ -27,7 +27,7 @@ static UNIMPLEMENTED_GRAMMARS: phf::Map<&'static str, &'static str> = phf_map! { "any" => "https://github.com/winglang/wing/issues/434", "Promise" => "https://github.com/winglang/wing/issues/529", "storage_modifier" => "https://github.com/winglang/wing/issues/107", - "access_modifier" => "https://github.com/winglang/wing/issues/108", + "internal" => "https://github.com/winglang/wing/issues/4156", "await_expression" => "https://github.com/winglang/wing/issues/116", "defer_expression" => "https://github.com/winglang/wing/issues/116", }; @@ -79,6 +79,7 @@ static RESERVED_WORDS: phf::Set<&'static str> = phf_set! { "private", "protected", "public", + "internal", "return", "short", "static", @@ -1298,7 +1299,7 @@ impl<'s> Parser<'s> { Some(am_node) => match self.node_text(&am_node) { "public" => Ok(AccessModifier::Public), "protected" => Ok(AccessModifier::Protected), - other => self.with_error(format!("Unknown access modifier {other}"), &am_node), + other => self.report_unimplemented_grammar(other, "access modifier", &am_node), }, None => Ok(AccessModifier::Private), } From 365ee1614045decddb6dc7042f829e984bdd29cb Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Tue, 12 Sep 2023 14:42:58 +0300 Subject: [PATCH 40/56] cr: better diag for public requirement of interface implemenations --- libs/wingc/src/ast.rs | 10 ++++++++++ libs/wingc/src/type_check.rs | 5 ++++- tools/hangar/__snapshots__/invalid.ts.snap | 8 ++++---- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/libs/wingc/src/ast.rs b/libs/wingc/src/ast.rs index 80510188512..08348c2b9a8 100644 --- a/libs/wingc/src/ast.rs +++ b/libs/wingc/src/ast.rs @@ -528,6 +528,16 @@ pub enum AccessModifier { Protected, } +impl Display for AccessModifier { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AccessModifier::Private => write!(f, "private"), + AccessModifier::Public => write!(f, "public"), + AccessModifier::Protected => write!(f, "protected"), + } + } +} + #[derive(Debug)] pub struct StructField { pub name: Symbol, diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index cb061d4a412..3f7f1695ae4 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -3505,7 +3505,10 @@ impl<'a> TypeChecker<'a> { if !matches!(class_method_var.access_modifier, AccessModifier::Public) { self.spanned_error( &class_method_var.name, - format!("Method \"{method_name}\" is not public but it's part of the \"{interface_type}\" interface",), + format!( + "Method \"{method_name}\" is {} in \"{}\" but it's an implementation of \"{interface_type}\". Interface members must be public.", + class_method_var.access_modifier, ast_class.name, + ), ); } } else { diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 6c6419f7b9e..cbcba480248 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -16,18 +16,18 @@ Duration " `; exports[`access_modifiers.w 1`] = ` -"error: Method \\"private_method\\" is not public but it's part of the \\"SomeInterface\\" interface +"error: Method \\"private_method\\" is private in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. --> ../../../examples/tests/invalid/access_modifiers.w:40:3 | 40 | private_method() {} - | ^^^^^^^^^^^^^^ Method \\"private_method\\" is not public but it's part of the \\"SomeInterface\\" interface + | ^^^^^^^^^^^^^^ Method \\"private_method\\" is private in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. -error: Method \\"protected_method\\" is not public but it's part of the \\"SomeInterface\\" interface +error: Method \\"protected_method\\" is protected in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. --> ../../../examples/tests/invalid/access_modifiers.w:38:13 | 38 | protected protected_method() {} - | ^^^^^^^^^^^^^^^^ Method \\"protected_method\\" is not public but it's part of the \\"SomeInterface\\" interface + | ^^^^^^^^^^^^^^^^ Method \\"protected_method\\" is protected in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. error: Cannot access protected member \\"protected_field\\" of \\"Foo\\" From 5e7c8c71c81e62a74293eb479c4d8821659d33c8 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Tue, 12 Sep 2023 16:33:55 +0300 Subject: [PATCH 41/56] cr: doc updates --- docs/docs/03-language-reference.md | 98 ++++++++++++++++++++++------- docs/docs/07-examples/08-classes.md | 16 ++--- 2 files changed, 83 insertions(+), 31 deletions(-) diff --git a/docs/docs/03-language-reference.md b/docs/docs/03-language-reference.md index 791cd393c1c..0f3a6b09327 100644 --- a/docs/docs/03-language-reference.md +++ b/docs/docs/03-language-reference.md @@ -654,7 +654,59 @@ Static class fields are not supported yet, see https://github.com/winglang/wing/ --- -### 1.5 Reassignability +### 1.5 Access Modifiers (member visibility) + +Class members, by default, can only be accessed from within the implementation code of the same class (private). +Inner classes or closures can access private members of their containing class. +```TS +class Foo { + private_field: num; // This is private by default + + init() {this.private_field = 1;} + + method() { + log(this.private_field); // We can access `private_field` since we're in Foo + + class InnerFoo { + method(f: Foo) { + log(f.private_field); // We can access `private_field` since we're in Foo + } + } + } +} +``` +Accessing class members of a super class can be done by adding the the `protected` access modifier. +```TS +class Foo { + protected protected_method() {}; // This is a `protected` method +} + +class Bar extends Foo { + method() { + this.protected_method(); // We can access `protected_method` from a subclass + } +} +``` +The `public` access modifier makes the class member accessible from anywhere. +Interface members are always public. +Implementing interface members in a class requires explicitly flagging them as `public`. +```TS +interface FooInterface { + public interface_method(): void; // Interface definitions are always implicitly `public` +} + +class Foo impl FooInterface { + public public_method() {} // This can be accessed from outside of the class implemenetation + public interface_method() {} // This must be explicitly defined as `public` since it's an interface implementation +} +let f = new Foo(); +f.public_method(); // We can call this method from outside the class - it's public +``` + +[`â–² top`][top] + +--- +### 1.6 Reassignability Re-assignment to variables that are defined with `let` is not allowed in Wing. @@ -700,7 +752,7 @@ let f = (arg1: num, var arg2: num) => { --- -### 1.6 Optionality +### 1.7 Optionality Nullity is a primary source of bugs in software. Being able to guarantee that a value will never be null makes it easier to write safe code without constantly having to take nullity into account. @@ -723,9 +775,9 @@ Here's a quick summary of how optionality works in Wing: * The keyword `nil` can be used in assignment scenarios to indicate that an optional doesn't have a value. It cannot be used to test if an optional has a value or not. -#### 1.6.1 Declaration +#### 1.7.1 Declaration -##### 1.6.1.1 Struct fields +##### 1.7.1.1 Struct fields One of the more common use cases for optionals is to use them in struct declarations. @@ -746,7 +798,7 @@ assert(david.address? == false); assert(jonathan.address? == true); ``` -##### 1.6.1.2 Variables +##### 1.7.1.2 Variables Use `T?` to indicate that a variable is optional. To initialize it without a value use `= nil`. @@ -764,7 +816,7 @@ x = nil; assert(x? == false); ``` -##### 1.6.1.3 Class fields +##### 1.7.1.3 Class fields Similarly to struct fields, fields of classes can be also defined as optional using `T?`: @@ -784,7 +836,7 @@ class Foo { } ``` -##### 1.6.1.4 Function arguments +##### 1.7.1.4 Function arguments In the following example, the argument `by` is optional, so it is possible to call `increment()` without supplying a value for `by`: @@ -826,7 +878,7 @@ f(myRequired: "hello"); f(myOptional: 12, myRequired: "dang"); ``` -##### 1.6.1.5 Function return types +##### 1.7.1.5 Function return types If a function returns an optional type, use the `return nil;` statement to indicate that the value is not defined. @@ -852,7 +904,7 @@ if let name = tryParseName("Neo Matrix") { } ``` -#### 1.6.2 Testing using `x?` +#### 1.7.2 Testing using `x?` To test if an optional has a value or not, you can either use `x == nil` or `x != nil` or the special syntax `x?`. @@ -883,7 +935,7 @@ if myPerson.address == nil { } ``` -#### 1.6.3 Unwrapping using `if let` +#### 1.7.3 Unwrapping using `if let` The `if let` statement (or `if let var` for a reassignable variable) can be used to test if an optional is defined and *unwrap* it into a non-optional variable defined inside the block: @@ -899,7 +951,7 @@ if let address = myPerson.address { > multiple conditions, or unwrapping multiple optionals. This is something we might consider in the > future. -#### 1.6.4 Unwrapping or default value using `??` +#### 1.7.4 Unwrapping or default value using `??` The `??` operator can be used to unwrap or provide a default value. This returns a value of `T` that can safely be used. @@ -908,7 +960,7 @@ can safely be used. let address: str = myPerson.address ?? "Planet Earth"; ``` -#### 1.6.5 Optional chaining using `?.` +#### 1.7.5 Optional chaining using `?.` The `?.` syntax can be used for optional chaining. Optional chaining returns a value of type `T?` which must be unwrapped in order to be used. @@ -925,7 +977,7 @@ if let ip = ipAddress { --- -#### 1.6.6 Roadmap +#### 1.7.6 Roadmap The following features are not yet implemented, but we are planning to add them in the future: @@ -944,7 +996,7 @@ The following features are not yet implemented, but we are planning to add them * Support `??` for different types if they have a common ancestor (and also think of interfaces). See https://github.com/winglang/wing/issues/2103 to track. -### 1.7 Type Inference +### 1.8 Type Inference Type can optionally be put between name and the equal sign, using a colon. Partial type inference is allowed while using the `?` keyword immediately after @@ -972,7 +1024,7 @@ Type annotations are required for method arguments and their return value but op --- -### 1.8 Error Handling +### 1.9 Error Handling Exceptions and `try/catch/finally` are the error mechanism. Mechanics directly translate to JavaScript. You can create a new exception with a `throw` call. @@ -997,7 +1049,7 @@ In the presence of `catch` the variable holding the exception (`e` in the exampl --- -### 1.9 Recommended Formatting +### 1.10 Recommended Formatting Wing recommends the following formatting and naming conventions: @@ -1013,7 +1065,7 @@ Wing recommends the following formatting and naming conventions: --- -### 1.10 Memory Management +### 1.11 Memory Management There is no implicit memory de-allocation function, dynamic memory is managed by Wing and is garbage collected (relying on JSII target GC for the meantime). @@ -1022,7 +1074,7 @@ Wing and is garbage collected (relying on JSII target GC for the meantime). --- -### 1.11 Execution Model +### 1.12 Execution Model Execution model currently is delegated to the JSII target. This means if you are targeting JSII with Node, Wing will use the event based loop that Node offers. @@ -1051,7 +1103,7 @@ AWS CDK or `TerraformApp` in case of CDK for Terraform target. --- -### 1.12 Asynchronous Model +### 1.13 Asynchronous Model Wing builds upon the asynchronous model of JavaScript currently and expands upon it with new keywords and concepts. The `async` keyword of JavaScript is replaced @@ -1064,17 +1116,17 @@ Main concepts to understand: Contrary to JavaScript, any call to an async function is implicitly awaited in Wing. -#### 1.12.1 Roadmap +#### 1.13.1 Roadmap The following features are not yet implemented, but we are planning to add them in the future: * `await`/`defer` statements - see https://github.com/winglang/wing/issues/116 to track. * Promise function type - see https://github.com/winglang/wing/issues/1004 to track. -### 1.13 Roadmap +### 1.14 Roadmap -Access modifiers (`private`/`public`/`internal`/`protected`) are not yet implemented. -See https://github.com/winglang/wing/issues/108 to track. +* Module type visibility (exports/`public` types) is not implemented yet - see https://github.com/winglang/wing/issues/130 to track. +* `internal` access modifier is not yet implemented - see https://github.com/winglang/wing/issues/4156 to track. ## 2. Statements diff --git a/docs/docs/07-examples/08-classes.md b/docs/docs/07-examples/08-classes.md index 60691e4b9dc..e77346f4009 100644 --- a/docs/docs/07-examples/08-classes.md +++ b/docs/docs/07-examples/08-classes.md @@ -28,7 +28,7 @@ class Foo { log("at inflight init"); } - inflight doStuff() { + public inflight doStuff() { // all code is async and runs on the cloud log("field3[0]='${this.field3.at(0)}'"); util.sleep(1s); @@ -55,7 +55,7 @@ interface IProfile { } inflight class WingPerson impl IProfile { - inflight name(): str { + public inflight name(): str { return "Fairy Wing"; } } @@ -84,10 +84,10 @@ class BucketBasedKeyValueStore impl IKVStore { init() { this.bucket = new cloud.Bucket(); } - inflight get(key: str): Json { + public inflight get(key: str): Json { return this.bucket.getJson(key); } - inflight set(key: str, value: Json): void { + public inflight set(key: str, value: Json): void { this.bucket.putJson(key, value); } } @@ -108,10 +108,10 @@ class BucketBasedKeyValueStore impl IKVStore { init() { this.bucket = new cloud.Bucket(); } - inflight get(key: str): Json { + public inflight get(key: str): Json { return this.bucket.getJson(key); } - inflight set(key: str, value: Json): void { + public inflight set(key: str, value: Json): void { this.bucket.putJson(key, value); } } @@ -127,10 +127,10 @@ class TableBasedKeyValueStore impl IKVStore { } ); } - inflight get(key: str): Json { + public inflight get(key: str): Json { return this.table.get(key); } - inflight set(key: str, value: Json): str { + public inflight set(key: str, value: Json): str { this.table.insert(key, value); } } From 76701cd23022bcb2fa6b0b09ddcda5b14a80cf65 Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Tue, 12 Sep 2023 13:52:14 +0000 Subject: [PATCH 42/56] chore: self mutation (build.diff) Signed-off-by: monada-bot[bot] --- libs/wingsdk/src/.gen/versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/wingsdk/src/.gen/versions.json b/libs/wingsdk/src/.gen/versions.json index fbe6adcd3fd..25acef56a47 100644 --- a/libs/wingsdk/src/.gen/versions.json +++ b/libs/wingsdk/src/.gen/versions.json @@ -1,6 +1,6 @@ { + "registry.terraform.io/hashicorp/aws": "4.65.0", "registry.terraform.io/hashicorp/random": "3.5.1", - "registry.terraform.io/hashicorp/google": "4.63.1", "registry.terraform.io/hashicorp/azurerm": "3.54.0", - "registry.terraform.io/hashicorp/aws": "4.65.0" + "registry.terraform.io/hashicorp/google": "4.63.1" } From 64d6c286a3ffe1b8bbf0b11b4a650b93cbbd08e0 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Tue, 12 Sep 2023 19:45:02 +0300 Subject: [PATCH 43/56] doc update --- docs/docs/03-language-reference.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/docs/03-language-reference.md b/docs/docs/03-language-reference.md index 0f3a6b09327..de9409afd2c 100644 --- a/docs/docs/03-language-reference.md +++ b/docs/docs/03-language-reference.md @@ -703,6 +703,9 @@ let f = new Foo(); f.public_method(); // We can call this method from outside the class - it's public ``` +Access modifier rules apply for both fields and methods of a class. +Struct fields are always public and do not have access modifiers. + [`â–² top`][top] --- From 50e412756c5332826d339735995c8660a7e07963 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 14 Sep 2023 09:48:13 +0300 Subject: [PATCH 44/56] test importing JSII access modifiers --- examples/tests/invalid/jsii_access_modifiers.w | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 examples/tests/invalid/jsii_access_modifiers.w diff --git a/examples/tests/invalid/jsii_access_modifiers.w b/examples/tests/invalid/jsii_access_modifiers.w new file mode 100644 index 00000000000..c1f79fb6097 --- /dev/null +++ b/examples/tests/invalid/jsii_access_modifiers.w @@ -0,0 +1,17 @@ +// Import a JSII module (our sdk) +bring cloud; + +let b = new cloud.Bucket(); + +class MyBucket extends cloud.Bucket { + method() { + // Call protected method from withing subclass (should work) + b.createTopic(cloud.BucketEventType.CREATE); + } +} + +b.createTopic(cloud.BucketEventType.CREATE); +//^ Cannot access protected member + +// Call public method from outside the class (should work) +b.addObject("k", "v"); \ No newline at end of file From 5223a6bf78972d31adaea3cef1c62a42e16827ab Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 14 Sep 2023 11:13:25 +0300 Subject: [PATCH 45/56] access modifiers and method overriding --- docs/docs/03-language-reference.md | 12 ++++++- examples/tests/invalid/access_modifiers.w | 37 ++++++++++++++++++++-- libs/wingc/src/ast.rs | 2 +- libs/wingc/src/type_check.rs | 38 +++++++++++++++++++++-- 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/docs/docs/03-language-reference.md b/docs/docs/03-language-reference.md index de9409afd2c..62450bf60d9 100644 --- a/docs/docs/03-language-reference.md +++ b/docs/docs/03-language-reference.md @@ -706,6 +706,17 @@ f.public_method(); // We can call this method from outside the class - it's publ Access modifier rules apply for both fields and methods of a class. Struct fields are always public and do not have access modifiers. +#### 1.5.1 Method overriding and access modifiers +Private methods cannot be overriden. +Overriding a method of a parent class requires the parent class's method to be either `public` or `protected`. +The overriding method can have either the same access modifier as the original method or a more permissive one. +You cannot "decrease" the access level down the inheritence hierarchy, only "increase" it. +In practice this means: +* `protected` methods can be overidden by either a `protected` or a `public` method. +* `public` methods can be overriden by a `public` method. + +Note that method overriding only applies to instance methods. `static` methods are not treated as part of the inheritence hierarcy. + [`â–² top`][top] --- @@ -1435,7 +1446,6 @@ In methods if return type is missing, `: void` is assumed. The following features are not yet implemented, but we are planning to add them in the future: * Overloading class methods (including `init`) - see https://github.com/winglang/wing/issues/3123 to track. -* Overriding class methods - see https://github.com/winglang/wing/issues/1124 to track. * Using the `final` keyword to stop the inheritance chain - see https://github.com/winglang/wing/issues/460 to track. [`â–² top`][top] diff --git a/examples/tests/invalid/access_modifiers.w b/examples/tests/invalid/access_modifiers.w index ff49475a0e7..025eb7d1c62 100644 --- a/examples/tests/invalid/access_modifiers.w +++ b/examples/tests/invalid/access_modifiers.w @@ -132,5 +132,38 @@ class BarBar { } } -// TODO: check jsii imported access modifiers -// TODO: add tests and implement checks for overriding methods with different access modifiers +// Test overriding methods with different access modifiers +// to from +// private private err +// private protected err +// private public err +// protected private err +// protected protected ok +// protected public err +// public private err +// public protected ok +// public public ok + +class FooOverrideToPrivate extends Foo { + public_method() {} + //^ Cannot override + protected_method() {} + //^ Cannot override + private_method() {} + //^ Cannot override +} + +class FooOverrideToProtected extends Foo { + protected public_method() {} + // ^ Cannot override + protected protected_method() {} + protected private_method() {} + // ^ Cannot override +} + +class FooOverrideToPublic extends Foo { + public public_method() {} + public protected_method() {} + public private_method() {} + // ^ Cannot override +} diff --git a/libs/wingc/src/ast.rs b/libs/wingc/src/ast.rs index 08348c2b9a8..9e661dc37f4 100644 --- a/libs/wingc/src/ast.rs +++ b/libs/wingc/src/ast.rs @@ -521,7 +521,7 @@ pub struct ClassField { pub access_modifier: AccessModifier, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum AccessModifier { Private, Public, diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index 3f7f1695ae4..0d6f088e712 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -3502,7 +3502,7 @@ impl<'a> TypeChecker<'a> { let class_method_type = class_method_var.type_; self.validate_type(class_method_type, method_type, &ast_class.name); // Make sure the method is public (interface methods must be public) - if !matches!(class_method_var.access_modifier, AccessModifier::Public) { + if class_method_var.access_modifier != AccessModifier::Public { self.spanned_error( &class_method_var.name, format!( @@ -4080,7 +4080,7 @@ impl<'a> TypeChecker<'a> { &mut self, method_sig: &ast::FunctionSignature, env: &mut SymbolEnv, - instance_type: Option, // TODO: change to bool, this can be inferred from the env (see `class_type` below) + instance_type: Option, access_modifier: AccessModifier, class_env: &mut SymbolEnv, method_name: &Symbol, @@ -4092,6 +4092,40 @@ impl<'a> TypeChecker<'a> { .expect("Expected method type to be a function") .this_type = instance_type; + // If this method is overriding a parent method, check access modifiers allow it, note this is only relevant for instance methods + if instance_type.is_some() { + if let Some(parent_type_env) = class_env.parent { + if let LookupResult::Found(SymbolKind::Variable(var), li) = parent_type_env.lookup_ext(method_name, None) { + let SymbolEnvKind::Type(method_defined_in) = li.env.kind else { + panic!("Expected env to be a type env"); + }; + // If parent method is private we don't allow overriding + if var.access_modifier == AccessModifier::Private { + self.spanned_error( + method_name, + format!("Cannot override private method \"{method_name}\" of \"{method_defined_in}\""), + ); + } else { + // For non private methods, we only allow overriding if the access modifier is the same or more permissive: + // - public can override public or protected + // - protected can only override protected + if !(access_modifier == AccessModifier::Public + && matches!(var.access_modifier, AccessModifier::Public | AccessModifier::Protected) + || access_modifier == AccessModifier::Protected && var.access_modifier == AccessModifier::Protected) + { + self.spanned_error( + method_name, + format!( + "Cannot override {} method \"{method_name}\" of \"{method_defined_in}\" with a {access_modifier} method", + var.access_modifier + ), + ); + } + } + } + } + } + match class_env.define( method_name, SymbolKind::make_member_variable( From 20d808da2f17efda26a3713ea805993e28bd1b4b Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 14 Sep 2023 11:36:23 +0300 Subject: [PATCH 46/56] fix after merge --- libs/wingc/src/parser.rs | 4 ++-- libs/wingc/src/type_check.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/wingc/src/parser.rs b/libs/wingc/src/parser.rs index 6cc7fdc0766..986e78dada7 100644 --- a/libs/wingc/src/parser.rs +++ b/libs/wingc/src/parser.rs @@ -10,8 +10,8 @@ use tree_sitter_traversal::{traverse, Order}; use crate::ast::{ AccessModifier, ArgList, AssignmentKind, BinaryOperator, BringSource, CalleeKind, CatchBlock, Class, ClassField, ElifBlock, ElifLetBlock, Expr, ExprKind, FunctionBody, FunctionDefinition, FunctionParameter, FunctionSignature, - IfLet, Interface, InterpolatedString, InterpolatedStringPart, Literal, NewExpr, Phase, Reference, Scope, Stmt, - StmtKind, StructField, Symbol, TypeAnnotation, TypeAnnotationKind, UnaryOperator, UserDefinedType, + IfLet, Interface, InterpolatedString, InterpolatedStringPart, Literal, NewExpr, Phase, Reference, Scope, Spanned, + Stmt, StmtKind, StructField, Symbol, TypeAnnotation, TypeAnnotationKind, UnaryOperator, UserDefinedType, }; use crate::comp_ctx::{CompilationContext, CompilationPhase}; use crate::diagnostic::{report_diagnostic, Diagnostic, DiagnosticResult, WingSpan}; diff --git a/libs/wingc/src/type_check.rs b/libs/wingc/src/type_check.rs index b2a1f208f35..3b3485f794e 100644 --- a/libs/wingc/src/type_check.rs +++ b/libs/wingc/src/type_check.rs @@ -3595,7 +3595,7 @@ impl<'a> TypeChecker<'a> { } BringSource::WingFile(name) => { let brought_env = match self.types.source_file_envs.get(Utf8Path::new(&name.name)) { - Some(env) => *env, *is_bringable), + Some(env) => *env, None => { self.spanned_error( stmt, From 23ac3bf3bc9662dceb6597d23bfcdf89e78fb55e Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Thu, 14 Sep 2023 08:55:14 +0000 Subject: [PATCH 47/56] chore: self mutation (e2e-2of2.diff) Signed-off-by: monada-bot[bot] --- tools/hangar/__snapshots__/invalid.ts.snap | 920 ++++++++++++--------- 1 file changed, 548 insertions(+), 372 deletions(-) diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index cbcba480248..7232d910bc2 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -1,8 +1,8 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`access_hidden_namespace.w 1`] = ` +exports[`access_hidden_namespace.main.w 1`] = ` "error: Unknown symbol \\"core\\" - --> ../../../examples/tests/invalid/access_hidden_namespace.w:7:5 + --> ../../../examples/tests/invalid/access_hidden_namespace.main.w:7:5 | 7 | new core.NodeJsCode(\\"/tmp/test.txt\\"); // This should fail even though \`fs.TextFile\` extends \`core.FileBase\` because we didn't bring in \`core\` explicitly. | ^^^^ Unknown symbol \\"core\\" @@ -16,7 +16,56 @@ Duration " `; exports[`access_modifiers.w 1`] = ` -"error: Method \\"private_method\\" is private in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. +"error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/access_modifiers.w:98:1 + | +98 | let foo = new Foo(); + | ^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/access_modifiers.w:100:1 + | +100 | log(foo.protected_field); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/access_modifiers.w:102:1 + | +102 | log(foo.private_field); + | ^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/access_modifiers.w:104:1 + | +104 | log(foo.public_field); + | ^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/access_modifiers.w:105:1 + | +105 | Foo.public_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/access_modifiers.w:106:1 + | +106 | Foo.protected_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/access_modifiers.w:108:1 + | +108 | Foo.private_static_method(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Method \\"private_method\\" is private in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. --> ../../../examples/tests/invalid/access_modifiers.w:40:3 | 40 | private_method() {} @@ -30,6 +79,20 @@ error: Method \\"protected_method\\" is protected in \\"Foo\\" but it's an imple | ^^^^^^^^^^^^^^^^ Method \\"protected_method\\" is protected in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. +error: Cannot override private method \\"method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:49:3 + | +49 | method() { + | ^^^^^^ Cannot override private method \\"method\\" of \\"Foo\\" + + +error: Cannot override private method \\"method\\" of \\"Bar\\" + --> ../../../examples/tests/invalid/access_modifiers.w:72:3 + | +72 | method() { + | ^^^^^^ Cannot override private method \\"method\\" of \\"Bar\\" + + error: Cannot access protected member \\"protected_field\\" of \\"Foo\\" --> ../../../examples/tests/invalid/access_modifiers.w:100:9 | @@ -58,6 +121,48 @@ error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" +error: Cannot override public method \\"public_method\\" of \\"Foo\\" with a private method + --> ../../../examples/tests/invalid/access_modifiers.w:148:3 + | +148 | public_method() {} + | ^^^^^^^^^^^^^ Cannot override public method \\"public_method\\" of \\"Foo\\" with a private method + + +error: Cannot override protected method \\"protected_method\\" of \\"Foo\\" with a private method + --> ../../../examples/tests/invalid/access_modifiers.w:150:3 + | +150 | protected_method() {} + | ^^^^^^^^^^^^^^^^ Cannot override protected method \\"protected_method\\" of \\"Foo\\" with a private method + + +error: Cannot override private method \\"private_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:152:3 + | +152 | private_method() {} + | ^^^^^^^^^^^^^^ Cannot override private method \\"private_method\\" of \\"Foo\\" + + +error: Cannot override public method \\"public_method\\" of \\"Foo\\" with a protected method + --> ../../../examples/tests/invalid/access_modifiers.w:157:13 + | +157 | protected public_method() {} + | ^^^^^^^^^^^^^ Cannot override public method \\"public_method\\" of \\"Foo\\" with a protected method + + +error: Cannot override private method \\"private_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:160:13 + | +160 | protected private_method() {} + | ^^^^^^^^^^^^^^ Cannot override private method \\"private_method\\" of \\"Foo\\" + + +error: Cannot override private method \\"private_method\\" of \\"Foo\\" + --> ../../../examples/tests/invalid/access_modifiers.w:167:10 + | +167 | public private_method() {} + | ^^^^^^^^^^^^^^ Cannot override private method \\"private_method\\" of \\"Foo\\" + + error: Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" --> ../../../examples/tests/invalid/access_modifiers.w:128:9 | @@ -156,37 +261,37 @@ Test Files 1 failed (1) Duration " `; -exports[`access_static_from_instance.w 1`] = ` +exports[`access_static_from_instance.main.w 1`] = ` "error: Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 - --> ../../../examples/tests/invalid/access_static_from_instance.w:4:3 + --> ../../../examples/tests/invalid/access_static_from_instance.main.w:4:3 | 4 | public static f: num; | ^^^^^^^^^^^^^^^^^^^^^ Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 error: Cannot access static property \\"f\\" from instance - --> ../../../examples/tests/invalid/access_static_from_instance.w:19:5 + --> ../../../examples/tests/invalid/access_static_from_instance.main.w:19:5 | 19 | foo.f; // Can't access static fields through instances | ^ Cannot access static property \\"f\\" from instance error: Cannot access static property \\"m\\" from instance - --> ../../../examples/tests/invalid/access_static_from_instance.w:20:5 + --> ../../../examples/tests/invalid/access_static_from_instance.main.w:20:5 | 20 | foo.m(); // Can't access static methods through instances | ^ Cannot access static property \\"m\\" from instance error: Unknown symbol \\"this\\" - --> ../../../examples/tests/invalid/access_static_from_instance.w:7:5 + --> ../../../examples/tests/invalid/access_static_from_instance.main.w:7:5 | 7 | this.instanceField = 1; // Can't access instance fields from static methods | ^^^^ Unknown symbol \\"this\\" error: Unknown symbol \\"this\\" - --> ../../../examples/tests/invalid/access_static_from_instance.w:8:5 + --> ../../../examples/tests/invalid/access_static_from_instance.main.w:8:5 | 8 | this.f = 1; // Can't access static fields through \`this\` | ^^^^ Unknown symbol \\"this\\" @@ -199,23 +304,23 @@ Test Files 1 failed (1) Duration " `; -exports[`bring.w 1`] = ` +exports[`bring.main.w 1`] = ` "error: Redundant bring of \\"std\\" - --> ../../../examples/tests/invalid/bring.w:1:1 + --> ../../../examples/tests/invalid/bring.main.w:1:1 | 1 | bring std; | ^^^^^^^^^^ Redundant bring of \\"std\\" error: \\"cloud\\" is already defined - --> ../../../examples/tests/invalid/bring.w:4:7 + --> ../../../examples/tests/invalid/bring.main.w:4:7 | 4 | bring cloud; | ^^^^^ \\"cloud\\" is already defined error: \\"fs\\" is not a built-in module - --> ../../../examples/tests/invalid/bring.w:6:1 + --> ../../../examples/tests/invalid/bring.main.w:6:1 | 6 | bring fs; | ^^^^^^^^^ \\"fs\\" is not a built-in module @@ -228,16 +333,16 @@ Test Files 1 failed (1) Duration " `; -exports[`bring_jsii.w 1`] = ` +exports[`bring_jsii.main.w 1`] = ` "error: bring \\"jsii-code-samples\\" must be assigned to an identifier (e.g. bring \\"foo\\" as foo) - --> ../../../examples/tests/invalid/bring_jsii.w:1:1 + --> ../../../examples/tests/invalid/bring_jsii.main.w:1:1 | 1 | bring \\"jsii-code-samples\\"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ bring \\"jsii-code-samples\\" must be assigned to an identifier (e.g. bring \\"foo\\" as foo) error: Cannot find module \\"foobar\\" in source directory: Unable to load \\"foobar\\": Module not found in \\"../../../examples/tests/invalid\\" - --> ../../../examples/tests/invalid/bring_jsii.w:4:1 + --> ../../../examples/tests/invalid/bring_jsii.main.w:4:1 | 4 | bring \\"foobar\\" as baz; | ^^^^^^^^^^^^^^^^^^^^^^ Cannot find module \\"foobar\\" in source directory: Unable to load \\"foobar\\": Module not found in \\"../../../examples/tests/invalid\\" @@ -250,16 +355,16 @@ Test Files 1 failed (1) Duration " `; -exports[`bring_local_self.w 1`] = ` +exports[`bring_local_self.main.w 1`] = ` "error: Cannot bring a module into itself - --> ../../../examples/tests/invalid/bring_local_self.w:1:1 + --> ../../../examples/tests/invalid/bring_local_self.main.w:1:1 | -1 | bring \\"./bring_local_self.w\\" as foo; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot bring a module into itself +1 | bring \\"./bring_local_self.main.w\\" as foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot bring a module into itself error: Cannot find module \\"../../../examples/tests/invalid/non-existent.w\\" - --> ../../../examples/tests/invalid/bring_local_self.w:4:1 + --> ../../../examples/tests/invalid/bring_local_self.main.w:4:1 | 4 | bring \\"./non-existent.w\\" as bar; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot find module \\"../../../examples/tests/invalid/non-existent.w\\" @@ -272,26 +377,33 @@ Test Files 1 failed (1) Duration " `; -exports[`bring_local_variables.w 1`] = ` -"error: Preflight field \\"x\\" is not initialized - --> ../../../examples/tests/invalid/file_with_variables.w:10:3 - | -10 | x: num; - | ^ Preflight field \\"x\\" is not initialized +exports[`bring_local_variables.main.w 1`] = ` +"error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/file_with_variables.w:5:1 + | +5 | let x = 5; + | ^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. -error: Cannot bring \\"../../../examples/tests/invalid/file_with_variables.w\\" - modules with statements besides classes, interfaces, enums, and structs cannot be brought - --> ../../../examples/tests/invalid/bring_local_variables.w:1:1 +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/file_with_variables.w:6:1 | -1 | bring \\"./file_with_variables.w\\" as stuff; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot bring \\"../../../examples/tests/invalid/file_with_variables.w\\" - modules with statements besides classes, interfaces, enums, and structs cannot be brought +6 | let y = [\\"hello\\", \\"world\\"]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. -error: Unknown symbol \\"stuff\\" - --> ../../../examples/tests/invalid/bring_local_variables.w:3:5 +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/file_with_variables.w:7:1 | -3 | new stuff.Bar(); - | ^^^^^ Unknown symbol \\"stuff\\" +7 | let z = new cloud.Bucket(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Preflight field \\"x\\" is not initialized + --> ../../../examples/tests/invalid/file_with_variables.w:10:3 + | +10 | x: num; + | ^ Preflight field \\"x\\" is not initialized @@ -301,23 +413,23 @@ Test Files 1 failed (1) Duration " `; -exports[`bring_non_std_construct.w 1`] = ` +exports[`bring_non_std_construct.main.w 1`] = ` "error: Expected 1 positional argument(s) but got 0 - --> ../../../examples/tests/invalid/bring_non_std_construct.w:8:1 + --> ../../../examples/tests/invalid/bring_non_std_construct.main.w:8:1 | 8 | new cdktf.S3Backend(); | ^^^^^^^^^^^^^^^^^^^^^ Expected 1 positional argument(s) but got 0 error: Cannot set id of non-standard preflight class \\"S3Backend\\" using \`as\` - --> ../../../examples/tests/invalid/bring_non_std_construct.w:13:85 + --> ../../../examples/tests/invalid/bring_non_std_construct.main.w:13:85 | 13 | new cdktf.S3Backend(this, cdktf.S3BackendConfig {bucket: \\"foo\\", key: \\"bar\\"}) as \\"s3_backend\\"; | ^^^^^^^^^^^^ Cannot set id of non-standard preflight class \\"S3Backend\\" using \`as\` error: Cannot set scope of non-standard preflight class \\"S3Backend\\" using \`in\` - --> ../../../examples/tests/invalid/bring_non_std_construct.w:15:85 + --> ../../../examples/tests/invalid/bring_non_std_construct.main.w:15:85 | 15 | new cdktf.S3Backend(this, cdktf.S3BackendConfig {bucket: \\"foo\\", key: \\"bar\\"}) in this; | ^^^^ Cannot set scope of non-standard preflight class \\"S3Backend\\" using \`in\` @@ -330,16 +442,16 @@ Test Files 1 failed (1) Duration " `; -exports[`call_inflight_from_preflight.w 1`] = ` +exports[`call_inflight_from_preflight.main.w 1`] = ` "error: Cannot call into inflight phase while preflight - --> ../../../examples/tests/invalid/call_inflight_from_preflight.w:4:1 + --> ../../../examples/tests/invalid/call_inflight_from_preflight.main.w:4:1 | 4 | util.sleep(1s); | ^^^^^^^^^^^^^^ Cannot call into inflight phase while preflight error: Cannot call into inflight phase while preflight - --> ../../../examples/tests/invalid/call_inflight_from_preflight.w:12:1 + --> ../../../examples/tests/invalid/call_inflight_from_preflight.main.w:12:1 | 12 | foo.do(); | ^^^^^^^^ Cannot call into inflight phase while preflight @@ -352,23 +464,23 @@ Test Files 1 failed (1) Duration " `; -exports[`capture_redefinition.w 1`] = ` +exports[`capture_redefinition.main.w 1`] = ` "error: Cannot access \\"y\\" because it is shadowed by another symbol with the same name - --> ../../../examples/tests/invalid/capture_redefinition.w:5:7 + --> ../../../examples/tests/invalid/capture_redefinition.main.w:5:7 | 5 | log(y); | ^ Cannot access \\"y\\" because it is shadowed by another symbol with the same name error: Cannot access \\"y\\" because it is shadowed by another symbol with the same name - --> ../../../examples/tests/invalid/capture_redefinition.w:14:9 + --> ../../../examples/tests/invalid/capture_redefinition.main.w:14:9 | 14 | log(y); | ^ Cannot access \\"y\\" because it is shadowed by another symbol with the same name error: Cannot access \\"x\\" because it is shadowed by another symbol with the same name - --> ../../../examples/tests/invalid/capture_redefinition.w:22:7 + --> ../../../examples/tests/invalid/capture_redefinition.main.w:22:7 | 22 | log(x); | ^ Cannot access \\"x\\" because it is shadowed by another symbol with the same name @@ -381,198 +493,198 @@ Test Files 1 failed (1) Duration " `; -exports[`class.w 1`] = ` +exports[`class.main.w 1`] = ` "error: Call to super constructor can only be made from derived classes - --> ../../../examples/tests/invalid/class.w:86:5 + --> ../../../examples/tests/invalid/class.main.w:86:5 | 86 | super(); | ^^^^^^^^ Call to super constructor can only be made from derived classes error: Call to super constructor must be first statement in constructor - --> ../../../examples/tests/invalid/class.w:98:5 + --> ../../../examples/tests/invalid/class.main.w:98:5 | 98 | super(name, major); | ^^^^^^^^^^^^^^^^^^^ Call to super constructor must be first statement in constructor error: Call to super constructor can only be done from within class constructor - --> ../../../examples/tests/invalid/class.w:103:5 + --> ../../../examples/tests/invalid/class.main.w:103:5 | 103 | super(\\"cool\\", \\"blue\\"); | ^^^^^^^^^^^^^^^^^^^^^^ Call to super constructor can only be done from within class constructor error: Call to super constructor can only be done from within a class constructor - --> ../../../examples/tests/invalid/class.w:108:4 + --> ../../../examples/tests/invalid/class.main.w:108:4 | 108 | super(); | ^^^^^^^^ Call to super constructor can only be done from within a class constructor error: Reserved method name. Initializers are declared with \\"init\\" - --> ../../../examples/tests/invalid/class.w:160:3 + --> ../../../examples/tests/invalid/class.main.w:160:3 | 160 | constructor() { | ^^^^^^^^^^^ Reserved method name. Initializers are declared with \\"init\\" error: Expected block - --> ../../../examples/tests/invalid/class.w:17:17 + --> ../../../examples/tests/invalid/class.main.w:17:17 | 17 | init(foo: str) | ^ Expected block error: Preflight field \\"x\\" is not initialized - --> ../../../examples/tests/invalid/class.w:4:4 + --> ../../../examples/tests/invalid/class.main.w:4:4 | 4 | x:num; | ^ Preflight field \\"x\\" is not initialized error: Expected 0 arguments but got 1 - --> ../../../examples/tests/invalid/class.w:9:1 + --> ../../../examples/tests/invalid/class.main.w:9:1 | 9 | new C2(1); | ^^^^^^^^^ Expected 0 arguments but got 1 -error: Expected 0 named arguments for func at ../../../examples/tests/invalid/class.w:13:1 - --> ../../../examples/tests/invalid/class.w:13:1 +error: Expected 0 named arguments for func at ../../../examples/tests/invalid/class.main.w:13:1 + --> ../../../examples/tests/invalid/class.main.w:13:1 | 13 | new C9(token: \\"1\\"); - | ^^^^^^^^^^^^^^^^^^ Expected 0 named arguments for func at ../../../examples/tests/invalid/class.w:13:1 + | ^^^^^^^^^^^^^^^^^^ Expected 0 named arguments for func at ../../../examples/tests/invalid/class.main.w:13:1 error: Expected 1 positional argument(s) but got 0 - --> ../../../examples/tests/invalid/class.w:19:1 + --> ../../../examples/tests/invalid/class.main.w:19:1 | 19 | new C10(); | ^^^^^^^^^ Expected 1 positional argument(s) but got 0 error: Expected 1 positional argument(s) but got 0 - --> ../../../examples/tests/invalid/class.w:22:1 + --> ../../../examples/tests/invalid/class.main.w:22:1 | 22 | new C10(foo: \\"bar\\"); | ^^^^^^^^^^^^^^^^^^^ Expected 1 positional argument(s) but got 0 error: No named arguments expected - --> ../../../examples/tests/invalid/class.w:25:1 + --> ../../../examples/tests/invalid/class.main.w:25:1 | 25 | new C10(\\"hello\\", foo: \\"bar\\"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ No named arguments expected error: Inflight field \\"x\\" is not initialized - --> ../../../examples/tests/invalid/class.w:37:16 + --> ../../../examples/tests/invalid/class.main.w:37:16 | 37 | inflight var x: num; | ^ Inflight field \\"x\\" is not initialized error: Inflight field \\"y\\" is not initialized - --> ../../../examples/tests/invalid/class.w:39:12 + --> ../../../examples/tests/invalid/class.main.w:39:12 | 39 | inflight y: str; | ^ Inflight field \\"y\\" is not initialized error: Inflight field \\"x\\" is not initialized - --> ../../../examples/tests/invalid/class.w:44:12 + --> ../../../examples/tests/invalid/class.main.w:44:12 | 44 | inflight x: num; | ^ Inflight field \\"x\\" is not initialized error: Inflight field \\"x\\" is not initialized - --> ../../../examples/tests/invalid/class.w:50:12 + --> ../../../examples/tests/invalid/class.main.w:50:12 | 50 | inflight x: num; | ^ Inflight field \\"x\\" is not initialized error: \\"y\\" cannot be initialized in the inflight initializer - --> ../../../examples/tests/invalid/class.w:61:10 + --> ../../../examples/tests/invalid/class.main.w:61:10 | 61 | this.y = 1; | ^ \\"y\\" cannot be initialized in the inflight initializer error: \\"x\\" cannot be initialized in the preflight initializer - --> ../../../examples/tests/invalid/class.w:56:10 + --> ../../../examples/tests/invalid/class.main.w:56:10 | 56 | this.x = 1; | ^ \\"x\\" cannot be initialized in the preflight initializer error: Preflight field \\"y\\" is not initialized - --> ../../../examples/tests/invalid/class.w:52:3 + --> ../../../examples/tests/invalid/class.main.w:52:3 | 52 | y: num; | ^ Preflight field \\"y\\" is not initialized error: Expected \\"x\\" to be a type but it's a variable - --> ../../../examples/tests/invalid/class.w:68:18 + --> ../../../examples/tests/invalid/class.main.w:68:18 | 68 | class C7 extends x { | ^ Expected \\"x\\" to be a type but it's a variable error: Expected \\"S1\\" to be a class - --> ../../../examples/tests/invalid/class.w:74:18 + --> ../../../examples/tests/invalid/class.main.w:74:18 | 74 | class C8 extends S1 { | ^^ Expected \\"S1\\" to be a class error: Unknown symbol \\"C11\\" - --> ../../../examples/tests/invalid/class.w:78:19 + --> ../../../examples/tests/invalid/class.main.w:78:19 | 78 | class C11 extends C11 { | ^^^ Unknown symbol \\"C11\\" error: Expected 1 positional argument(s) but got 0 - --> ../../../examples/tests/invalid/class.w:157:5 + --> ../../../examples/tests/invalid/class.main.w:157:5 | 157 | super(); | ^^^^^^^^ Expected 1 positional argument(s) but got 0 error: Expected 1 arguments but got 2 - --> ../../../examples/tests/invalid/class.w:141:5 + --> ../../../examples/tests/invalid/class.main.w:141:5 | 141 | super(someNum, someStr); | ^^^^^^^^^^^^^^^^^^^^^^^^ Expected 1 arguments but got 2 error: Expected 1 positional argument(s) but got 0 - --> ../../../examples/tests/invalid/class.w:132:5 + --> ../../../examples/tests/invalid/class.main.w:132:5 | 132 | super(); | ^^^^^^^^ Expected 1 positional argument(s) but got 0 error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/class.w:123:11 + --> ../../../examples/tests/invalid/class.main.w:123:11 | 123 | super(someStr); | ^^^^^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Variable cannot be reassigned from inflight - --> ../../../examples/tests/invalid/class.w:61:5 + --> ../../../examples/tests/invalid/class.main.w:61:5 | 61 | this.y = 1; | ^^^^^^ Variable cannot be reassigned from inflight error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/class.w:31:14 + --> ../../../examples/tests/invalid/class.main.w:31:14 | 31 | this.x = \\"Hi\\"; | ^^^^ Expected type to be \\"num\\", but got \\"str\\" instead @@ -585,9 +697,9 @@ Test Files 1 failed (1) Duration " `; -exports[`cloud_function_expects_inflight.w 1`] = ` +exports[`cloud_function_expects_inflight.main.w 1`] = ` "error: Expected type to be \\"inflight (event: str): void\\", but got \\"preflight (name: str): str\\" instead - --> ../../../examples/tests/invalid/cloud_function_expects_inflight.w:3:20 + --> ../../../examples/tests/invalid/cloud_function_expects_inflight.main.w:3:20 | 3 | new cloud.Function((name: str): str => { | /--------------------^ @@ -597,7 +709,7 @@ exports[`cloud_function_expects_inflight.w 1`] = ` error: Expected type to be \\"inflight (message: str): void\\", but got \\"inflight (x: num): unknown\\" instead - --> ../../../examples/tests/invalid/cloud_function_expects_inflight.w:9:15 + --> ../../../examples/tests/invalid/cloud_function_expects_inflight.main.w:9:15 | 9 | q.setConsumer(inflight (x: num) => { | /---------------^ @@ -614,135 +726,135 @@ Test Files 1 failed (1) Duration " `; -exports[`container_types.w 1`] = ` +exports[`container_types.main.w 1`] = ` "error: Unknown parser error - --> ../../../examples/tests/invalid/container_types.w:14:25 + --> ../../../examples/tests/invalid/container_types.main.w:14:25 | 14 | let m2: Map = [\\"a\\" => 1, \\"b\\" => \\"2\\", \\"c\\" => 3]; | ^^^^ Unknown parser error error: Unexpected 'string' - --> ../../../examples/tests/invalid/container_types.w:14:31 + --> ../../../examples/tests/invalid/container_types.main.w:14:31 | 14 | let m2: Map = [\\"a\\" => 1, \\"b\\" => \\"2\\", \\"c\\" => 3]; | ^^^ Unexpected 'string' error: Unknown parser error - --> ../../../examples/tests/invalid/container_types.w:14:47 + --> ../../../examples/tests/invalid/container_types.main.w:14:47 | 14 | let m2: Map = [\\"a\\" => 1, \\"b\\" => \\"2\\", \\"c\\" => 3]; | ^^^^ Unknown parser error error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/container_types.w:2:28 + --> ../../../examples/tests/invalid/container_types.main.w:2:28 | 2 | let arr1: Array = [1, \\"2\\", 3]; | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected \\"Set\\" or \\"MutSet\\", found \\"Array\\" - --> ../../../examples/tests/invalid/container_types.w:3:12 + --> ../../../examples/tests/invalid/container_types.main.w:3:12 | 3 | let arr2 = Array {1, 2, 3}; | ^^^^^^^^^^ Expected \\"Set\\" or \\"MutSet\\", found \\"Array\\" error: Expected type to be \\"Array\\", but got \\"Array\\" instead - --> ../../../examples/tests/invalid/container_types.w:5:24 + --> ../../../examples/tests/invalid/container_types.main.w:5:24 | 5 | let arr4: Array = arr3; | ^^^^ Expected type to be \\"Array\\", but got \\"Array\\" instead error: Unknown symbol \\"someRandomMethod\\" - --> ../../../examples/tests/invalid/container_types.w:6:6 + --> ../../../examples/tests/invalid/container_types.main.w:6:6 | 6 | arr1.someRandomMethod(); | ^^^^^^^^^^^^^^^^ Unknown symbol \\"someRandomMethod\\" error: Expected type to be \\"num\\", but got \\"num?\\" instead - --> ../../../examples/tests/invalid/container_types.w:9:16 + --> ../../../examples/tests/invalid/container_types.main.w:9:16 | 9 | let val: num = arr5.tryAt(0); | ^^^^^^^^^^^^^ Expected type to be \\"num\\", but got \\"num?\\" instead error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/container_types.w:13:38 + --> ../../../examples/tests/invalid/container_types.main.w:13:38 | 13 | let m1: Map = {\\"a\\" => 1, \\"b\\" => \\"2\\", \\"c\\" => 3}; | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected type to be \\"Map\\", but got \\"Array\\" instead - --> ../../../examples/tests/invalid/container_types.w:14:20 + --> ../../../examples/tests/invalid/container_types.main.w:14:20 | 14 | let m2: Map = [\\"a\\" => 1, \\"b\\" => \\"2\\", \\"c\\" => 3]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Expected type to be \\"Map\\", but got \\"Array\\" instead error: Expected type to be \\"Map\\", but got \\"Map\\" instead - --> ../../../examples/tests/invalid/container_types.w:16:20 + --> ../../../examples/tests/invalid/container_types.main.w:16:20 | 16 | let m4: Map = m3; | ^^ Expected type to be \\"Map\\", but got \\"Map\\" instead error: Unknown symbol \\"someRandomMethod\\" - --> ../../../examples/tests/invalid/container_types.w:17:4 + --> ../../../examples/tests/invalid/container_types.main.w:17:4 | 17 | m1.someRandomMethod(); | ^^^^^^^^^^^^^^^^ Unknown symbol \\"someRandomMethod\\" error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/container_types.w:20:24 + --> ../../../examples/tests/invalid/container_types.main.w:20:24 | 20 | let s1: Set = {1, \\"2\\", 3}; | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected \\"Array\\" or \\"MutArray\\", found \\"Set\\" - --> ../../../examples/tests/invalid/container_types.w:21:10 + --> ../../../examples/tests/invalid/container_types.main.w:21:10 | 21 | let s2 = Set [1, \\"2\\", 3]; | ^^^^^^^^ Expected \\"Array\\" or \\"MutArray\\", found \\"Set\\" error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/container_types.w:22:24 + --> ../../../examples/tests/invalid/container_types.main.w:22:24 | 22 | let s3: Set = [1, \\"2\\", 3]; | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected type to be \\"Set\\", but got \\"Array\\" instead - --> ../../../examples/tests/invalid/container_types.w:22:20 + --> ../../../examples/tests/invalid/container_types.main.w:22:20 | 22 | let s3: Set = [1, \\"2\\", 3]; | ^^^^^^^^^^^ Expected type to be \\"Set\\", but got \\"Array\\" instead error: Expected type to be \\"Set\\", but got \\"Set\\" instead - --> ../../../examples/tests/invalid/container_types.w:24:20 + --> ../../../examples/tests/invalid/container_types.main.w:24:20 | 24 | let s5: Set = s4; | ^^ Expected type to be \\"Set\\", but got \\"Set\\" instead error: Unknown symbol \\"someRandomMethod\\" - --> ../../../examples/tests/invalid/container_types.w:25:4 + --> ../../../examples/tests/invalid/container_types.main.w:25:4 | 25 | s1.someRandomMethod(); | ^^^^^^^^^^^^^^^^ Unknown symbol \\"someRandomMethod\\" error: Expected type to be \\"Array\\", but got \\"MutArray\\" instead - --> ../../../examples/tests/invalid/container_types.w:27:21 + --> ../../../examples/tests/invalid/container_types.main.w:27:21 | 27 | let a: Array = MutArray[]; | ^^^^^^^^^^^^^^^ Expected type to be \\"Array\\", but got \\"MutArray\\" instead @@ -839,9 +951,9 @@ Test Files 1 failed (1) Duration " `; -exports[`diags_with_multibyte_chars.w 1`] = ` +exports[`diags_with_multibyte_chars.main.w 1`] = ` "error: Unknown symbol \\"asdf\\" - --> ../../../examples/tests/invalid/diags_with_multibyte_chars.w:4:1 + --> ../../../examples/tests/invalid/diags_with_multibyte_chars.main.w:4:1 | 4 | asdf; | ^^^^ Unknown symbol \\"asdf\\" @@ -854,16 +966,16 @@ Test Files 1 failed (1) Duration " `; -exports[`enums.w 1`] = ` +exports[`enums.main.w 1`] = ` "error: Enum \\"SomeEnum\\" does not contain value \\"FOUR\\" - --> ../../../examples/tests/invalid/enums.w:5:21 + --> ../../../examples/tests/invalid/enums.main.w:5:21 | 5 | let four = SomeEnum.FOUR; | ^^^^ Enum \\"SomeEnum\\" does not contain value \\"FOUR\\" error: Property not found - --> ../../../examples/tests/invalid/enums.w:8:24 + --> ../../../examples/tests/invalid/enums.main.w:8:24 | 8 | let two = SomeEnum.TWO.TWO; | ^^^ Property not found @@ -876,16 +988,16 @@ Test Files 1 failed (1) Duration " `; -exports[`extern.w 1`] = ` +exports[`extern.main.w 1`] = ` "error: Failed to resolve extern \\"./sad.js\\": Not Found - --> ../../../examples/tests/invalid/extern.w:2:3 + --> ../../../examples/tests/invalid/extern.main.w:2:3 | 2 | extern \\"./sad.js\\" static getNum(): num; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Failed to resolve extern \\"./sad.js\\": Not Found error: Failed to resolve extern \\"not-installed\\": Not Found - --> ../../../examples/tests/invalid/extern.w:4:3 + --> ../../../examples/tests/invalid/extern.main.w:4:3 | 4 | extern \\"not-installed\\" static tooBad(): bool; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Failed to resolve extern \\"not-installed\\": Not Found @@ -898,9 +1010,9 @@ Test Files 1 failed (1) Duration " `; -exports[`extern_static.w 1`] = ` +exports[`extern_static.main.w 1`] = ` "error: Extern methods must be declared \\"static\\" (they cannot access instance members) - --> ../../../examples/tests/invalid/extern_static.w:2:39 + --> ../../../examples/tests/invalid/extern_static.main.w:2:39 | 2 | extern \\"../external_js.js\\" inflight getGreeting(name: str): str; | ^^^^^^^^^^^ Extern methods must be declared \\"static\\" (they cannot access instance members) @@ -914,7 +1026,28 @@ Duration " `; exports[`file_with_variables.w 1`] = ` -"error: Preflight field \\"x\\" is not initialized +"error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/file_with_variables.w:5:1 + | +5 | let x = 5; + | ^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/file_with_variables.w:6:1 + | +6 | let y = [\\"hello\\", \\"world\\"]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/file_with_variables.w:7:1 + | +7 | let z = new cloud.Bucket(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Preflight field \\"x\\" is not initialized --> ../../../examples/tests/invalid/file_with_variables.w:10:3 | 10 | x: num; @@ -928,16 +1061,16 @@ Test Files 1 failed (1) Duration " `; -exports[`for_loop.w 1`] = ` +exports[`for_loop.main.w 1`] = ` "error: Reserved word - --> ../../../examples/tests/invalid/for_loop.w:5:5 + --> ../../../examples/tests/invalid/for_loop.main.w:5:5 | 5 | for test in bucket { | ^^^^ Reserved word error: Unable to iterate over \\"Bucket\\" - --> ../../../examples/tests/invalid/for_loop.w:5:13 + --> ../../../examples/tests/invalid/for_loop.main.w:5:13 | 5 | for test in bucket { | ^^^^^^ Unable to iterate over \\"Bucket\\" @@ -950,16 +1083,16 @@ Test Files 1 failed (1) Duration " `; -exports[`function_type.w 1`] = ` +exports[`function_type.main.w 1`] = ` "error: Expected function return type - --> ../../../examples/tests/invalid/function_type.w:2:26 + --> ../../../examples/tests/invalid/function_type.main.w:2:26 | 2 | let my_func = (callback: (num)) => { }; | ^^^^^ Expected function return type error: Expected function return type - --> ../../../examples/tests/invalid/function_type.w:4:28 + --> ../../../examples/tests/invalid/function_type.main.w:4:28 | 4 | let my_func2 = (callback: ((num)): (str)) => { }; | ^^^^^ Expected function return type @@ -972,51 +1105,51 @@ Test Files 1 failed (1) Duration " `; -exports[`function_variadic_definition.w 1`] = ` +exports[`function_variadic_definition.main.w 1`] = ` "error: Unknown parser error - --> ../../../examples/tests/invalid/function_variadic_definition.w:15:13 + --> ../../../examples/tests/invalid/function_variadic_definition.main.w:15:13 | 15 | f5(args: 1, 2); | ^ Unknown parser error error: Variadic parameters must always be the last parameter in a function. - --> ../../../examples/tests/invalid/function_variadic_definition.w:1:14 + --> ../../../examples/tests/invalid/function_variadic_definition.main.w:1:14 | 1 | let f1 = (...args: Array, x:num) => {}; | ^^^^ Variadic parameters must always be the last parameter in a function. error: Variadic parameters must always be the last parameter in a function. - --> ../../../examples/tests/invalid/function_variadic_definition.w:4:14 + --> ../../../examples/tests/invalid/function_variadic_definition.main.w:4:14 | 4 | let f2 = (...nums: Array, ...strs: Array) => {}; | ^^^^ Variadic parameters must always be the last parameter in a function. error: Expected type to be num, but got bool instead. - --> ../../../examples/tests/invalid/function_variadic_definition.w:8:7 + --> ../../../examples/tests/invalid/function_variadic_definition.main.w:8:7 | 8 | f3(1, true, 2); | ^^^^ Expected type to be num, but got bool instead. error: Variadic parameters must be type Array or MutArray. - --> ../../../examples/tests/invalid/function_variadic_definition.w:11:14 + --> ../../../examples/tests/invalid/function_variadic_definition.main.w:11:14 | 11 | let f4 = (...args: Set) => {}; | ^^^^ Variadic parameters must be type Array or MutArray. error: No named arguments expected - --> ../../../examples/tests/invalid/function_variadic_definition.w:15:1 + --> ../../../examples/tests/invalid/function_variadic_definition.main.w:15:1 | 15 | f5(args: 1, 2); | ^^^^^^^^^^^^^^ No named arguments expected error: Expected type to be Bucket, but got bool instead. - --> ../../../examples/tests/invalid/function_variadic_definition.w:24:21 + --> ../../../examples/tests/invalid/function_variadic_definition.main.w:24:21 | 24 | funcBucket(bucket1, true, bucket2); | ^^^^ Expected type to be Bucket, but got bool instead. @@ -1029,9 +1162,9 @@ Test Files 1 failed (1) Duration " `; -exports[`immutable_container_types.w 1`] = ` +exports[`immutable_container_types.main.w 1`] = ` "error: Unknown symbol \\"set\\" - --> ../../../examples/tests/invalid/immutable_container_types.w:3:4 + --> ../../../examples/tests/invalid/immutable_container_types.main.w:3:4 | 3 | m1.set(\\"a\\", \\"bye\\"); | ^^^ Unknown symbol \\"set\\" @@ -1044,44 +1177,44 @@ Test Files 1 failed (1) Duration " `; -exports[`impl_interface.w 1`] = ` +exports[`impl_interface.main.w 1`] = ` "error: Class \\"A\\" does not implement method \\"handle\\" of interface \\"IQueueSetConsumerHandler\\" - --> ../../../examples/tests/invalid/impl_interface.w:3:7 + --> ../../../examples/tests/invalid/impl_interface.main.w:3:7 | 3 | class A impl cloud.IQueueSetConsumerHandler { | ^ Class \\"A\\" does not implement method \\"handle\\" of interface \\"IQueueSetConsumerHandler\\" error: Expected type to be \\"inflight (message: str): void\\", but got \\"inflight (x: num): void\\" instead - --> ../../../examples/tests/invalid/impl_interface.w:7:7 + --> ../../../examples/tests/invalid/impl_interface.main.w:7:7 | 7 | class B impl cloud.IQueueSetConsumerHandler { | ^ Expected type to be \\"inflight (message: str): void\\", but got \\"inflight (x: num): void\\" instead error: Expected an interface, instead found type \\"Bucket\\" - --> ../../../examples/tests/invalid/impl_interface.w:14:14 + --> ../../../examples/tests/invalid/impl_interface.main.w:14:14 | 14 | class C impl cloud.Bucket { | ^^^^^^^^^^^^ Expected an interface, instead found type \\"Bucket\\" error: Class \\"r\\" does not implement method \\"method1\\" of interface \\"I3\\" - --> ../../../examples/tests/invalid/impl_interface.w:30:7 + --> ../../../examples/tests/invalid/impl_interface.main.w:30:7 | 30 | class r impl I3 { | ^ Class \\"r\\" does not implement method \\"method1\\" of interface \\"I3\\" error: Class \\"r\\" does not implement method \\"method2\\" of interface \\"I3\\" - --> ../../../examples/tests/invalid/impl_interface.w:30:7 + --> ../../../examples/tests/invalid/impl_interface.main.w:30:7 | 30 | class r impl I3 { | ^ Class \\"r\\" does not implement method \\"method2\\" of interface \\"I3\\" error: Class \\"r\\" does not implement method \\"method3\\" of interface \\"I3\\" - --> ../../../examples/tests/invalid/impl_interface.w:30:7 + --> ../../../examples/tests/invalid/impl_interface.main.w:30:7 | 30 | class r impl I3 { | ^ Class \\"r\\" does not implement method \\"method3\\" of interface \\"I3\\" @@ -1094,65 +1227,65 @@ Test Files 1 failed (1) Duration " `; -exports[`inference.w 1`] = ` +exports[`inference.main.w 1`] = ` "error: Missing required type annotation for method signature - --> ../../../examples/tests/invalid/inference.w:78:8 + --> ../../../examples/tests/invalid/inference.main.w:78:8 | 78 | args(nice) { | ^^^^ Missing required type annotation for method signature error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/inference.w:13:18 + --> ../../../examples/tests/invalid/inference.main.w:13:18 | 13 | recursiveClosure(\\"\\"); | ^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected type to be \\"str\\", but got \\"num\\" instead - --> ../../../examples/tests/invalid/inference.w:32:19 + --> ../../../examples/tests/invalid/inference.main.w:32:19 | 32 | stringArray2.push(2); | ^ Expected type to be \\"str\\", but got \\"num\\" instead error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/inference.w:38:16 + --> ../../../examples/tests/invalid/inference.main.w:38:16 | 38 | numArray2.push(\\"2\\"); | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/inference.w:42:40 + --> ../../../examples/tests/invalid/inference.main.w:42:40 | 42 | let dependentArray = [numArray2.at(0), stringArray2.at(1)]; | ^^^^^^^^^^^^^^^^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/inference.w:45:60 + --> ../../../examples/tests/invalid/inference.main.w:45:60 | 45 | let dependentMap = { \\"cool\\" => numArray2.at(0), \\"cool2\\" => stringArray2.at(1) }; | ^^^^^^^^^^^^^^^^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected type to be \\"inflight (key: str, type: BucketEventType): void\\", but got \\"inflight (request: ApiRequest): ApiResponse\\" instead - --> ../../../examples/tests/invalid/inference.w:57:31 + --> ../../../examples/tests/invalid/inference.main.w:57:31 | 57 | (new cloud.Bucket()).onCreate(func); | ^^^^ Expected type to be \\"inflight (key: str, type: BucketEventType): void\\", but got \\"inflight (request: ApiRequest): ApiResponse\\" instead error: Expected type to be \\"inflight (str): void\\", but got \\"inflight (arg1: num): unknown\\" instead - --> ../../../examples/tests/invalid/inference.w:84:37 + --> ../../../examples/tests/invalid/inference.main.w:84:37 | 84 | let badFunc: inflight (str): void = inflight (arg1: num) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Expected type to be \\"inflight (str): void\\", but got \\"inflight (arg1: num): unknown\\" instead error: Inferred type Array conflicts with already inferred type Array - --> ../../../examples/tests/invalid/inference.w:92:33 + --> ../../../examples/tests/invalid/inference.main.w:92:33 | 92 | let jsonDoubleInference: SS = { | /---------------------------------^ @@ -1163,84 +1296,84 @@ error: Inferred type Array conflicts with already inferred type Array error: Unexpected return value from void function. Return type annotations are required for methods. - --> ../../../examples/tests/invalid/inference.w:75:5 + --> ../../../examples/tests/invalid/inference.main.w:75:5 | 75 | return true; | ^^^^^^^^^^^^ Unexpected return value from void function. Return type annotations are required for methods. error: Property not found - --> ../../../examples/tests/invalid/inference.w:63:19 + --> ../../../examples/tests/invalid/inference.main.w:63:19 | 63 | body: request.body, | ^^^^ Property not found error: Unable to infer type - --> ../../../examples/tests/invalid/inference.w:60:23 + --> ../../../examples/tests/invalid/inference.main.w:60:23 | 60 | let func2 = inflight (request) => { | ^^^^^^^ Unable to infer type error: Unable to infer type - --> ../../../examples/tests/invalid/inference.w:25:44 + --> ../../../examples/tests/invalid/inference.main.w:25:44 | 25 | let stringInterpolationCannotBeInferred = (nice) => { | ^^^^ Unable to infer type error: Unable to infer type - --> ../../../examples/tests/invalid/inference.w:4:29 + --> ../../../examples/tests/invalid/inference.main.w:4:29 | 4 | let preflightClosureArgs = (nice) => { return true; }; | ^^^^ Unable to infer type error: Unable to infer type - --> ../../../examples/tests/invalid/inference.w:69:5 + --> ../../../examples/tests/invalid/inference.main.w:69:5 | 69 | let anotherEmptyArray = []; | ^^^^^^^^^^^^^^^^^ Unable to infer type error: Unable to infer type - --> ../../../examples/tests/invalid/inference.w:21:5 + --> ../../../examples/tests/invalid/inference.main.w:21:5 | 21 | let clonedArray = emptyArray.copyMut(); | ^^^^^^^^^^^ Unable to infer type error: Unable to infer type - --> ../../../examples/tests/invalid/inference.w:16:5 + --> ../../../examples/tests/invalid/inference.main.w:16:5 | 16 | let emptyArray = []; | ^^^^^^^^^^ Unable to infer type error: Unable to infer type - --> ../../../examples/tests/invalid/inference.w:60:5 + --> ../../../examples/tests/invalid/inference.main.w:60:5 | 60 | let func2 = inflight (request) => { | ^^^^^ Unable to infer type error: Unable to infer type - --> ../../../examples/tests/invalid/inference.w:18:5 + --> ../../../examples/tests/invalid/inference.main.w:18:5 | 18 | let numArray = emptyArray; | ^^^^^^^^ Unable to infer type error: Unable to infer type - --> ../../../examples/tests/invalid/inference.w:4:5 + --> ../../../examples/tests/invalid/inference.main.w:4:5 | 4 | let preflightClosureArgs = (nice) => { return true; }; | ^^^^^^^^^^^^^^^^^^^^ Unable to infer type error: Unable to infer type - --> ../../../examples/tests/invalid/inference.w:25:5 + --> ../../../examples/tests/invalid/inference.main.w:25:5 | 25 | let stringInterpolationCannotBeInferred = (nice) => { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unable to infer type @@ -1253,37 +1386,37 @@ Test Files 1 failed (1) Duration " `; -exports[`inflight_class_created_in_preflight.w 1`] = ` +exports[`inflight_class_created_in_preflight.main.w 1`] = ` "error: Cannot create inflight class \\"Foo\\" in preflight phase - --> ../../../examples/tests/invalid/inflight_class_created_in_preflight.w:3:1 + --> ../../../examples/tests/invalid/inflight_class_created_in_preflight.main.w:3:1 | 3 | new Foo(); | ^^^^^^^^^ Cannot create inflight class \\"Foo\\" in preflight phase error: Cannot create preflight class \\"PreflightClass\\" in inflight phase - --> ../../../examples/tests/invalid/inflight_class_created_in_preflight.w:19:3 + --> ../../../examples/tests/invalid/inflight_class_created_in_preflight.main.w:19:3 | 19 | new PreflightClass(); | ^^^^^^^^^^^^^^^^^^^^ Cannot create preflight class \\"PreflightClass\\" in inflight phase error: Cannot create inflight class \\"Foo\\" in preflight phase - --> ../../../examples/tests/invalid/inflight_class_created_in_preflight.w:13:5 + --> ../../../examples/tests/invalid/inflight_class_created_in_preflight.main.w:13:5 | 13 | new Foo(); | ^^^^^^^^^ Cannot create inflight class \\"Foo\\" in preflight phase error: Cannot create inflight class \\"Foo\\" in preflight phase - --> ../../../examples/tests/invalid/inflight_class_created_in_preflight.w:8:5 + --> ../../../examples/tests/invalid/inflight_class_created_in_preflight.main.w:8:5 | 8 | new Foo(); | ^^^^^^^^^ Cannot create inflight class \\"Foo\\" in preflight phase error: Cannot qualify access to a lifted type \\"PreflightClass\\" (see https://github.com/winglang/wing/issues/76 for more details) - --> ../../../examples/tests/invalid/inflight_class_created_in_preflight.w:19:7 + --> ../../../examples/tests/invalid/inflight_class_created_in_preflight.main.w:19:7 | 19 | new PreflightClass(); | ^^^^^^^^^^^^^^ Cannot qualify access to a lifted type \\"PreflightClass\\" (see https://github.com/winglang/wing/issues/76 for more details) @@ -1296,9 +1429,9 @@ Test Files 1 failed (1) Duration " `; -exports[`inflight_class_dup_init.w 1`] = ` +exports[`inflight_class_dup_init.main.w 1`] = ` "error: Multiple inflight initializers defined in class Foo - --> ../../../examples/tests/invalid/inflight_class_dup_init.w:6:3 + --> ../../../examples/tests/invalid/inflight_class_dup_init.main.w:6:3 | 6 | / inflight init() { 7 | | @@ -1313,9 +1446,9 @@ Test Files 1 failed (1) Duration " `; -exports[`inflight_class_in_preflight.w 1`] = ` +exports[`inflight_class_in_preflight.main.w 1`] = ` "error: Cannot create inflight class \\"Foo\\" in preflight phase - --> ../../../examples/tests/invalid/inflight_class_in_preflight.w:5:1 + --> ../../../examples/tests/invalid/inflight_class_in_preflight.main.w:5:1 | 5 | new Foo(); | ^^^^^^^^^ Cannot create inflight class \\"Foo\\" in preflight phase @@ -1328,9 +1461,9 @@ Test Files 1 failed (1) Duration " `; -exports[`inflight_class_interface_structural_typing.w 1`] = ` +exports[`inflight_class_interface_structural_typing.main.w 1`] = ` "error: Expected type to be \\"IGoo\\", but got \\"NotGoo\\" instead - --> ../../../examples/tests/invalid/inflight_class_interface_structural_typing.w:26:17 + --> ../../../examples/tests/invalid/inflight_class_interface_structural_typing.main.w:26:17 | 26 | let x: IGoo = new NotGoo(); | ^^^^^^^^^^^^ Expected type to be \\"IGoo\\", but got \\"NotGoo\\" instead @@ -1343,16 +1476,16 @@ Test Files 1 failed (1) Duration " `; -exports[`inflight_reassign.w 1`] = ` +exports[`inflight_reassign.main.w 1`] = ` "error: Variable cannot be reassigned from inflight - --> ../../../examples/tests/invalid/inflight_reassign.w:5:3 + --> ../../../examples/tests/invalid/inflight_reassign.main.w:5:3 | 5 | xvar = \\"hi\\"; | ^^^^ Variable cannot be reassigned from inflight error: Variable is not reassignable - --> ../../../examples/tests/invalid/inflight_reassign.w:8:3 + --> ../../../examples/tests/invalid/inflight_reassign.main.w:8:3 | 8 | ylet = 456; | ^^^^ Variable is not reassignable @@ -1365,23 +1498,23 @@ Test Files 1 failed (1) Duration " `; -exports[`inflight_ref_explicit_ops.w 1`] = ` +exports[`inflight_ref_explicit_ops.main.w 1`] = ` "error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) - --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:13:12 + --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.main.w:13:12 | 13 | return this.myQueue; | ^^^^^^^^^^^^ Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) error: Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) - --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:34:13 + --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.main.w:34:13 | 34 | let x = this.b; | ^^^^^^ Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) error: Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) - --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.w:47:13 + --> ../../../examples/tests/invalid/inflight_ref_explicit_ops.main.w:47:13 | 47 | let b = this.array.at(1); | ^^^^^^^^^^^^^^^^ Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) @@ -1394,16 +1527,16 @@ Test Files 1 failed (1) Duration " `; -exports[`inflight_ref_resource_sub_method.w 1`] = ` +exports[`inflight_ref_resource_sub_method.main.w 1`] = ` "error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) - --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:13:12 + --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.main.w:13:12 | 13 | return this.myQueue; | ^^^^^^^^^^^^ Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) error: Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) - --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.w:18:12 + --> ../../../examples/tests/invalid/inflight_ref_resource_sub_method.main.w:18:12 | 18 | return globalQueue; | ^^^^^^^^^^^ Cannot qualify access to a lifted object of type \\"Queue\\" (see https://github.com/winglang/wing/issues/76 for more details) @@ -1416,16 +1549,16 @@ Test Files 1 failed (1) Duration " `; -exports[`inflight_ref_unknown_op.w 1`] = ` +exports[`inflight_ref_unknown_op.main.w 1`] = ` "error: Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) - --> ../../../examples/tests/invalid/inflight_ref_unknown_op.w:13:13 + --> ../../../examples/tests/invalid/inflight_ref_unknown_op.main.w:13:13 | 13 | let x = this.b; | ^^^^^^ Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) error: Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) - --> ../../../examples/tests/invalid/inflight_ref_unknown_op.w:17:13 + --> ../../../examples/tests/invalid/inflight_ref_unknown_op.main.w:17:13 | 17 | let y = globalB; | ^^^^^^^ Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) @@ -1438,44 +1571,44 @@ Test Files 1 failed (1) Duration " `; -exports[`interface.w 1`] = ` +exports[`interface.main.w 1`] = ` "error: Properties are not supported in interfaces - --> ../../../examples/tests/invalid/interface.w:30:3 + --> ../../../examples/tests/invalid/interface.main.w:30:3 | 30 | bar: str; | ^^^^^^^^^ Properties are not supported in interfaces error: Unknown symbol \\"IB\\" - --> ../../../examples/tests/invalid/interface.w:2:22 + --> ../../../examples/tests/invalid/interface.main.w:2:22 | 2 | interface IA extends IB { | ^^ Unknown symbol \\"IB\\" error: Unknown symbol \\"IDontExist\\" - --> ../../../examples/tests/invalid/interface.w:10:26 + --> ../../../examples/tests/invalid/interface.main.w:10:26 | 10 | interface IExist extends IDontExist { | ^^^^^^^^^^ Unknown symbol \\"IDontExist\\" error: Expected an interface, instead found type \\"ISomeClass\\" - --> ../../../examples/tests/invalid/interface.w:16:34 + --> ../../../examples/tests/invalid/interface.main.w:16:34 | 16 | interface ISomeInterface extends ISomeClass { | ^^^^^^^^^^ Expected an interface, instead found type \\"ISomeClass\\" error: Symbol \\"foo\\" already defined in this scope - --> ../../../examples/tests/invalid/interface.w:23:5 + --> ../../../examples/tests/invalid/interface.main.w:23:5 | 23 | foo(): void; | ^^^ Symbol \\"foo\\" already defined in this scope error: Symbol \\"foo\\" already defined in this scope - --> ../../../examples/tests/invalid/interface.w:25:5 + --> ../../../examples/tests/invalid/interface.main.w:25:5 | 25 | foo(): num; | ^^^ Symbol \\"foo\\" already defined in this scope @@ -1488,9 +1621,9 @@ Test Files 1 failed (1) Duration " `; -exports[`issue_2767.w 1`] = ` +exports[`issue_2767.main.w 1`] = ` "error: Expected type to be \\"MutJson\\", but got \\"Bucket\\" instead - --> ../../../examples/tests/invalid/issue_2767.w:4:16 + --> ../../../examples/tests/invalid/issue_2767.main.w:4:16 | 4 | x.set(\\"hello\\", new cloud.Bucket()); | ^^^^^^^^^^^^^^^^^^ Expected type to be \\"MutJson\\", but got \\"Bucket\\" instead @@ -1503,79 +1636,115 @@ Test Files 1 failed (1) Duration " `; -exports[`json.w 1`] = ` +exports[`jsii_access_modifiers.w 1`] = ` +"error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/jsii_access_modifiers.w:4:1 + | +4 | let b = new cloud.Bucket(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/jsii_access_modifiers.w:13:1 + | +13 | b.createTopic(cloud.BucketEventType.CREATE); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + --> ../../../examples/tests/invalid/jsii_access_modifiers.w:17:1 + | +17 | b.addObject(\\"k\\", \\"v\\"); + | ^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. + + +error: Cannot access protected member \\"createTopic\\" of \\"Bucket\\" + --> ../../../examples/tests/invalid/jsii_access_modifiers.w:13:3 + | +13 | b.createTopic(cloud.BucketEventType.CREATE); + | ^^^^^^^^^^^ Cannot access protected member \\"createTopic\\" of \\"Bucket\\" + + + + +Tests 1 failed (1) +Test Files 1 failed (1) +Duration " +`; + +exports[`json.main.w 1`] = ` "error: Json literal must have an element - --> ../../../examples/tests/invalid/json.w:29:26 + --> ../../../examples/tests/invalid/json.main.w:29:26 | 29 | let jsonIncomplete = Json; | ^ Json literal must have an element error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/json.w:6:14 + --> ../../../examples/tests/invalid/json.main.w:6:14 | 6 | let n: num = j; | ^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected type to be \\"bool\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/json.w:8:15 + --> ../../../examples/tests/invalid/json.main.w:8:15 | 8 | let b: bool = j; | ^ Expected type to be \\"bool\\", but got \\"str\\" instead error: Expected type to be \\"Map\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/json.w:10:19 + --> ../../../examples/tests/invalid/json.main.w:10:19 | 10 | let m: Map = j; | ^ Expected type to be \\"Map\\", but got \\"str\\" instead error: Expected type to be \\"Set\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/json.w:12:20 + --> ../../../examples/tests/invalid/json.main.w:12:20 | 12 | let s2: Set = j; | ^ Expected type to be \\"Set\\", but got \\"str\\" instead error: Expected type to be \\"Array\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/json.w:14:21 + --> ../../../examples/tests/invalid/json.main.w:14:21 | 14 | let a: Array = j; | ^ Expected type to be \\"Array\\", but got \\"str\\" instead error: Unknown symbol \\"set\\" - --> ../../../examples/tests/invalid/json.w:19:13 + --> ../../../examples/tests/invalid/json.main.w:19:13 | 19 | foreverJson.set(\\"a\\", \\"world!\\"); | ^^^ Unknown symbol \\"set\\" error: Expected type to be \\"num?\\", but got \\"str?\\" instead - --> ../../../examples/tests/invalid/json.w:32:20 + --> ../../../examples/tests/invalid/json.main.w:32:20 | 32 | let tryNum: num? = j.tryAsStr(); | ^^^^^^^^^^^^ Expected type to be \\"num?\\", but got \\"str?\\" instead error: Expected type to be \\"str?\\", but got \\"bool?\\" instead - --> ../../../examples/tests/invalid/json.w:35:20 + --> ../../../examples/tests/invalid/json.main.w:35:20 | 35 | let tryStr: str? = j.tryAsBool(); | ^^^^^^^^^^^^^ Expected type to be \\"str?\\", but got \\"bool?\\" instead error: Expected type to be \\"bool?\\", but got \\"num?\\" instead - --> ../../../examples/tests/invalid/json.w:38:22 + --> ../../../examples/tests/invalid/json.main.w:38:22 | 38 | let tryBool: bool? = j.tryAsNum(); | ^^^^^^^^^^^^ Expected type to be \\"bool?\\", but got \\"num?\\" instead error: Missing required field \\"maybe\\" from \\"StructyJson\\" - --> ../../../examples/tests/invalid/json.w:55:40 + --> ../../../examples/tests/invalid/json.main.w:55:40 | 55 | let notJsonMissingField: StructyJson = { | /----------------------------------------^ @@ -1586,56 +1755,56 @@ error: Missing required field \\"maybe\\" from \\"StructyJson\\" error: Expected type to be \\"bool\\", but got \\"num\\" instead - --> ../../../examples/tests/invalid/json.w:65:11 + --> ../../../examples/tests/invalid/json.main.w:65:11 | 65 | good: 2, | ^ Expected type to be \\"bool\\", but got \\"num\\" instead error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/json.w:72:14 + --> ../../../examples/tests/invalid/json.main.w:72:14 | 72 | stuff: [1, \\"hi\\", 3], | ^^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/json.w:83:8 + --> ../../../examples/tests/invalid/json.main.w:83:8 | 83 | b: \\"\\", | ^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected type to be \\"StructyJson\\", but got \\"Json\\" instead (hint: use StructyJson.fromJson() to convert dynamic Json) - --> ../../../examples/tests/invalid/json.w:96:38 + --> ../../../examples/tests/invalid/json.main.w:96:38 | 96 | let mutableJsonStruct: StructyJson = mutableJson; | ^^^^^^^^^^^ Expected type to be \\"StructyJson\\", but got \\"Json\\" instead (hint: use StructyJson.fromJson() to convert dynamic Json) error: \\"Array\\" is not a legal JSON value - --> ../../../examples/tests/invalid/json.w:23:17 + --> ../../../examples/tests/invalid/json.main.w:23:17 | 23 | let jArr = Json [bkt]; | ^^^^^ \\"Array\\" is not a legal JSON value error: \\"Bucket\\" is not a legal JSON value - --> ../../../examples/tests/invalid/json.w:26:28 + --> ../../../examples/tests/invalid/json.main.w:26:28 | 26 | let jsonObj = Json { boom: bkt }; | ^^^ \\"Bucket\\" is not a legal JSON value error: \\"Bucket\\" is not a legal JSON value - --> ../../../examples/tests/invalid/json.w:100:6 + --> ../../../examples/tests/invalid/json.main.w:100:6 | 100 | b: new cloud.Bucket() | ^^^^^^^^^^^^^^^^^^ \\"Bucket\\" is not a legal JSON value error: \\"Bucket\\" is not a legal JSON value - --> ../../../examples/tests/invalid/json.w:104:21 + --> ../../../examples/tests/invalid/json.main.w:104:21 | 104 | let isBucket = Json new cloud.Bucket(); | ^^^^^^^^^^^^^^^^^^ \\"Bucket\\" is not a legal JSON value @@ -1648,9 +1817,9 @@ Test Files 1 failed (1) Duration " `; -exports[`json_static.w 1`] = ` +exports[`json_static.main.w 1`] = ` "error: Unknown symbol \\"set\\" - --> ../../../examples/tests/invalid/json_static.w:4:10 + --> ../../../examples/tests/invalid/json_static.main.w:4:10 | 4 | immutObj.set(\\"a\\", \\"foo\\"); | ^^^ Unknown symbol \\"set\\" @@ -1663,26 +1832,26 @@ Test Files 1 failed (1) Duration " `; -exports[`missing_semicolon.w 1`] = ` +exports[`missing_semicolon.main.w 1`] = ` "error: Expected ';' - --> ../../../examples/tests/invalid/missing_semicolon.w:9:3 + --> ../../../examples/tests/invalid/missing_semicolon.main.w:9:3 | 9 | }) | ^ Expected ';' error: Expected ';' - --> ../../../examples/tests/invalid/missing_semicolon.w:16:10 + --> ../../../examples/tests/invalid/missing_semicolon.main.w:16:9 | 16 | let x = 5 // - | ^ Expected ';' + | ^ Expected ';' error: Expected '}' - --> ../../../examples/tests/invalid/missing_semicolon.w:19:14 + --> ../../../examples/tests/invalid/missing_semicolon.main.w:19:13 | 19 | if (x > 10) { - | ^ Expected '}' + | ^ Expected '}' @@ -1692,100 +1861,100 @@ Test Files 1 failed (1) Duration " `; -exports[`mut_container_types.w 1`] = ` +exports[`mut_container_types.main.w 1`] = ` "error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/mut_container_types.w:2:29 + --> ../../../examples/tests/invalid/mut_container_types.main.w:2:29 | 2 | let arr1 = MutArray[1, \\"2\\", 3]; | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected \\"Set\\" or \\"MutSet\\", found \\"MutArray\\" - --> ../../../examples/tests/invalid/mut_container_types.w:3:12 + --> ../../../examples/tests/invalid/mut_container_types.main.w:3:12 | 3 | let arr2 = MutArray{1, 2, 3}; | ^^^^^^^^^^^^^ Expected \\"Set\\" or \\"MutSet\\", found \\"MutArray\\" error: Expected type to be \\"MutArray\\", but got \\"Array\\" instead - --> ../../../examples/tests/invalid/mut_container_types.w:4:27 + --> ../../../examples/tests/invalid/mut_container_types.main.w:4:27 | 4 | let arr3: MutArray = [1, 2, 3]; // https://github.com/winglang/wing/issues/1117 | ^^^^^^^^^ Expected type to be \\"MutArray\\", but got \\"Array\\" instead error: Expected type to be \\"MutArray\\", but got \\"MutArray\\" instead - --> ../../../examples/tests/invalid/mut_container_types.w:6:27 + --> ../../../examples/tests/invalid/mut_container_types.main.w:6:27 | 6 | let arr5: MutArray = arr4; | ^^^^ Expected type to be \\"MutArray\\", but got \\"MutArray\\" instead error: Unknown symbol \\"someMethod\\" - --> ../../../examples/tests/invalid/mut_container_types.w:7:6 + --> ../../../examples/tests/invalid/mut_container_types.main.w:7:6 | 7 | arr1.someMethod(); | ^^^^^^^^^^ Unknown symbol \\"someMethod\\" error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/mut_container_types.w:10:25 + --> ../../../examples/tests/invalid/mut_container_types.main.w:10:25 | 10 | let s1 = MutSet{1, \\"2\\", 3}; | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected \\"Array\\" or \\"MutArray\\", found \\"MutSet\\" - --> ../../../examples/tests/invalid/mut_container_types.w:11:10 + --> ../../../examples/tests/invalid/mut_container_types.main.w:11:10 | 11 | let s2 = MutSet[1, \\"2\\", 3]; | ^^^^^^^^^^^ Expected \\"Array\\" or \\"MutArray\\", found \\"MutSet\\" error: Expected type to be \\"MutSet\\", but got \\"Set\\" instead - --> ../../../examples/tests/invalid/mut_container_types.w:12:23 + --> ../../../examples/tests/invalid/mut_container_types.main.w:12:23 | 12 | let s3: MutSet = {1, 1, 3}; // https://github.com/winglang/wing/issues/1117 | ^^^^^^^^^ Expected type to be \\"MutSet\\", but got \\"Set\\" instead error: Expected type to be \\"MutSet\\", but got \\"MutSet\\" instead - --> ../../../examples/tests/invalid/mut_container_types.w:14:23 + --> ../../../examples/tests/invalid/mut_container_types.main.w:14:23 | 14 | let s5: MutSet = s4; | ^^ Expected type to be \\"MutSet\\", but got \\"MutSet\\" instead error: Unknown symbol \\"someMethod\\" - --> ../../../examples/tests/invalid/mut_container_types.w:15:4 + --> ../../../examples/tests/invalid/mut_container_types.main.w:15:4 | 15 | s3.someMethod(); | ^^^^^^^^^^ Unknown symbol \\"someMethod\\" error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/mut_container_types.w:18:33 + --> ../../../examples/tests/invalid/mut_container_types.main.w:18:33 | 18 | let m1 = MutMap{\\"hello\\" => \\"world\\"}; | ^^^^^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected \\"Array\\" or \\"MutArray\\", found \\"MutMap\\" - --> ../../../examples/tests/invalid/mut_container_types.w:20:10 + --> ../../../examples/tests/invalid/mut_container_types.main.w:20:10 | 20 | let m2 = MutMap[\\"hello\\", \\"world\\"]; | ^^^^^^^^^^^ Expected \\"Array\\" or \\"MutArray\\", found \\"MutMap\\" error: Expected type to be \\"MutMap\\", but got \\"Map\\" instead - --> ../../../examples/tests/invalid/mut_container_types.w:22:23 + --> ../../../examples/tests/invalid/mut_container_types.main.w:22:23 | 22 | let m3: MutMap = {\\"hello\\" => \\"world\\"}; | ^^^^^^^^^^^^^^^^^^^^ Expected type to be \\"MutMap\\", but got \\"Map\\" instead error: Expected type to be \\"MutMap\\", but got \\"MutMap\\" instead - --> ../../../examples/tests/invalid/mut_container_types.w:25:23 + --> ../../../examples/tests/invalid/mut_container_types.main.w:25:23 | 25 | let m5: MutMap = m4; | ^^ Expected type to be \\"MutMap\\", but got \\"MutMap\\" instead @@ -1798,37 +1967,37 @@ Test Files 1 failed (1) Duration " `; -exports[`nil.w 1`] = ` +exports[`nil.main.w 1`] = ` "error: Expected type to be \\"str\\", but got \\"nil\\" instead (hint: to allow \\"nil\\" assignment use optional type: \\"str?\\") - --> ../../../examples/tests/invalid/nil.w:3:14 + --> ../../../examples/tests/invalid/nil.main.w:3:14 | 3 | let x: str = nil; | ^^^ Expected type to be \\"str\\", but got \\"nil\\" instead (hint: to allow \\"nil\\" assignment use optional type: \\"str?\\") error: Expected optional type, found \\"nil\\" - --> ../../../examples/tests/invalid/nil.w:24:4 + --> ../../../examples/tests/invalid/nil.main.w:24:4 | 24 | if nil? { | ^^^ Expected optional type, found \\"nil\\" error: Cannot assign nil value to variables without explicit optional type - --> ../../../examples/tests/invalid/nil.w:28:18 + --> ../../../examples/tests/invalid/nil.main.w:28:18 | 28 | let nilWannabe = nil; | ^^^ Cannot assign nil value to variables without explicit optional type error: Cannot assign nil value to variables without explicit optional type - --> ../../../examples/tests/invalid/nil.w:31:17 + --> ../../../examples/tests/invalid/nil.main.w:31:17 | 31 | let nilGaggle = [nil, nil, nil]; | ^^^^^^^^^^^^^^^ Cannot assign nil value to variables without explicit optional type error: Expected type to be \\"num\\", but got \\"nil\\" instead (hint: to allow \\"nil\\" assignment use optional type: \\"num?\\") - --> ../../../examples/tests/invalid/nil.w:20:14 + --> ../../../examples/tests/invalid/nil.main.w:20:14 | 20 | foo.setBar(nil); | ^^^ Expected type to be \\"num\\", but got \\"nil\\" instead (hint: to allow \\"nil\\" assignment use optional type: \\"num?\\") @@ -1841,93 +2010,93 @@ Test Files 1 failed (1) Duration " `; -exports[`optionals.w 1`] = ` +exports[`optionals.main.w 1`] = ` "error: Expected type to be \\"num\\", but got \\"num?\\" instead - --> ../../../examples/tests/invalid/optionals.w:11:3 + --> ../../../examples/tests/invalid/optionals.main.w:11:3 | 11 | f(x); | ^ Expected type to be \\"num\\", but got \\"num?\\" instead error: Expected type to be \\"num?\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/optionals.w:14:11 + --> ../../../examples/tests/invalid/optionals.main.w:14:11 | 14 | fOptional(\\"\\"); | ^^ Expected type to be \\"num?\\", but got \\"str\\" instead error: Expected optional type, found \\"bool\\" - --> ../../../examples/tests/invalid/optionals.w:18:4 + --> ../../../examples/tests/invalid/optionals.main.w:18:4 | 18 | if y? { | ^ Expected optional type, found \\"bool\\" error: Expected optional type, found \\"bool\\" - --> ../../../examples/tests/invalid/optionals.w:22:9 + --> ../../../examples/tests/invalid/optionals.main.w:22:9 | 22 | let z = y ?? 1; | ^ Expected optional type, found \\"bool\\" error: Expected type to be \\"str\\", but got \\"num\\" instead - --> ../../../examples/tests/invalid/optionals.w:25:14 + --> ../../../examples/tests/invalid/optionals.main.w:25:14 | 25 | let w: str = x ?? 3; | ^^^^^^ Expected type to be \\"str\\", but got \\"num\\" instead error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/optionals.w:28:6 + --> ../../../examples/tests/invalid/optionals.main.w:28:6 | 28 | x ?? \\"hello\\"; | ^^^^^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected type to be \\"Sub1\\", but got \\"Sub2\\" instead - --> ../../../examples/tests/invalid/optionals.w:39:17 + --> ../../../examples/tests/invalid/optionals.main.w:39:17 | 39 | optionalSub1 ?? new Sub2(); | ^^^^^^^^^^ Expected type to be \\"Sub1\\", but got \\"Sub2\\" instead error: Expected type to be \\"Sub1\\", but got \\"Super\\" instead - --> ../../../examples/tests/invalid/optionals.w:41:17 + --> ../../../examples/tests/invalid/optionals.main.w:41:17 | 41 | optionalSub1 ?? new Super(); | ^^^^^^^^^^^ Expected type to be \\"Sub1\\", but got \\"Super\\" instead error: Expected type to be optional, but got \\"bool\\" instead - --> ../../../examples/tests/invalid/optionals.w:45:12 + --> ../../../examples/tests/invalid/optionals.main.w:45:12 | 45 | if let x = true { | ^^^^ Expected type to be optional, but got \\"bool\\" instead error: Property access on optional type \\"A?\\" requires optional accessor: \\"?.\\" - --> ../../../examples/tests/invalid/optionals.w:68:9 + --> ../../../examples/tests/invalid/optionals.main.w:68:9 | 68 | let c = b.a.val; | ^^^ Property access on optional type \\"A?\\" requires optional accessor: \\"?.\\" error: Expected type to be \\"str\\", but got \\"str?\\" instead - --> ../../../examples/tests/invalid/optionals.w:91:16 + --> ../../../examples/tests/invalid/optionals.main.w:91:16 | 91 | let val: str = baz?.bar?.foo?.val; | ^^^^^^^^^^^^^^^^^^ Expected type to be \\"str\\", but got \\"str?\\" instead error: Cannot call an optional function - --> ../../../examples/tests/invalid/optionals.w:95:1 + --> ../../../examples/tests/invalid/optionals.main.w:95:1 | 95 | optionalFunction(); | ^^^^^^^^^^^^^^^^ Cannot call an optional function error: Variable is not reassignable - --> ../../../examples/tests/invalid/optionals.w:53:3 + --> ../../../examples/tests/invalid/optionals.main.w:53:3 | 53 | hi = \\"bye\\"; | ^^ Variable is not reassignable @@ -1940,9 +2109,9 @@ Test Files 1 failed (1) Duration " `; -exports[`panic.w 1`] = ` +exports[`panic.main.w 1`] = ` "error: Compiler bug (panicked at 'User invoked panic', libs/wingc/src/type_check.rs:LINE:COL) during type-checking, please report at https://www.winglang.io/contributing/start-here/bugs - --> ../../../examples/tests/invalid/panic.w:6:1 + --> ../../../examples/tests/invalid/panic.main.w:6:1 | 6 | 😱; | ^^ Compiler bug (panicked at 'User invoked panic', libs/wingc/src/type_check.rs:LINE:COL) during type-checking, please report at https://www.winglang.io/contributing/start-here/bugs @@ -1955,11 +2124,11 @@ Test Files 1 failed (1) Duration " `; -exports[`panic.w 2`] = `"Panicked, backtrace not captured: Unsupported"`; +exports[`panic.main.w 2`] = `"Panicked, backtrace not captured: Unsupported"`; -exports[`preflight_from_inflight.w 1`] = ` +exports[`preflight_from_inflight.main.w 1`] = ` "error: Cannot call into preflight phase while inflight - --> ../../../examples/tests/invalid/preflight_from_inflight.w:15:5 + --> ../../../examples/tests/invalid/preflight_from_inflight.main.w:15:5 | 15 | this.r.myPreflight(); | ^^^^^^^^^^^^^^^^^^^^ Cannot call into preflight phase while inflight @@ -1972,30 +2141,30 @@ Test Files 1 failed (1) Duration " `; -exports[`primitives.w 1`] = ` +exports[`primitives.main.w 1`] = ` "error: Unexpected reference \\"structured_access_expression\\" - --> ../../../examples/tests/invalid/primitives.w:5:5 + --> ../../../examples/tests/invalid/primitives.main.w:5:5 | 5 | log(y[0]); | ^^^^ Unexpected reference \\"structured_access_expression\\" error: Unknown symbol \\"blabla\\" - --> ../../../examples/tests/invalid/primitives.w:9:16 + --> ../../../examples/tests/invalid/primitives.main.w:9:16 | 9 | let join = arr.blabla(\\",\\"); | ^^^^^^ Unknown symbol \\"blabla\\" error: Unknown symbol \\"push\\" - --> ../../../examples/tests/invalid/primitives.w:11:5 + --> ../../../examples/tests/invalid/primitives.main.w:11:5 | 11 | arr.push(4); | ^^^^ Unknown symbol \\"push\\" error: Expected type to be \\"str\\", but got \\"num\\" instead - --> ../../../examples/tests/invalid/primitives.w:13:14 + --> ../../../examples/tests/invalid/primitives.main.w:13:14 | 13 | let n: str = arr.at(0); | ^^^^^^^^^ Expected type to be \\"str\\", but got \\"num\\" instead @@ -2008,37 +2177,37 @@ Test Files 1 failed (1) Duration " `; -exports[`reassign_to_nonreassignable.w 1`] = ` +exports[`reassign_to_nonreassignable.main.w 1`] = ` "error: Variable is not reassignable - --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:3:1 + --> ../../../examples/tests/invalid/reassign_to_nonreassignable.main.w:3:1 | 3 | x = x + 1; | ^ Variable is not reassignable error: Variable is not reassignable - --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:42:3 + --> ../../../examples/tests/invalid/reassign_to_nonreassignable.main.w:42:3 | 42 | arg = 0; | ^^^ Variable is not reassignable error: Variable is not reassignable - --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:35:5 + --> ../../../examples/tests/invalid/reassign_to_nonreassignable.main.w:35:5 | 35 | this.inflightF = this.inflightF + 1; | ^^^^^^^^^^^^^^ Variable is not reassignable error: Variable is not reassignable - --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:28:5 + --> ../../../examples/tests/invalid/reassign_to_nonreassignable.main.w:28:5 | 28 | this.f = this.f + 1; | ^^^^^^ Variable is not reassignable error: Variable is not reassignable - --> ../../../examples/tests/invalid/reassign_to_nonreassignable.w:30:5 + --> ../../../examples/tests/invalid/reassign_to_nonreassignable.main.w:30:5 | 30 | this.innerR.inner = 2; | ^^^^^^^^^^^^^^^^^ Variable is not reassignable @@ -2051,9 +2220,9 @@ Test Files 1 failed (1) Duration " `; -exports[`resource_access_field_as_method.w 1`] = ` +exports[`resource_access_field_as_method.main.w 1`] = ` "error: Expected a function or method, found \\"str\\" - --> ../../../examples/tests/invalid/resource_access_field_as_method.w:9:1 + --> ../../../examples/tests/invalid/resource_access_field_as_method.main.w:9:1 | 9 | x.name(); | ^^^^^^ Expected a function or method, found \\"str\\" @@ -2066,9 +2235,9 @@ Test Files 1 failed (1) Duration " `; -exports[`resource_captures.w 1`] = ` +exports[`resource_captures.main.w 1`] = ` "error: Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) - --> ../../../examples/tests/invalid/resource_captures.w:13:13 + --> ../../../examples/tests/invalid/resource_captures.main.w:13:13 | 13 | let b = this.bucket; | ^^^^^^^^^^^ Cannot qualify access to a lifted object of type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) @@ -2081,16 +2250,16 @@ Test Files 1 failed (1) Duration " `; -exports[`resource_inflight.w 1`] = ` +exports[`resource_inflight.main.w 1`] = ` "error: Cannot create preflight class \\"Bucket\\" in inflight phase - --> ../../../examples/tests/invalid/resource_inflight.w:4:3 + --> ../../../examples/tests/invalid/resource_inflight.main.w:4:3 | 4 | new cloud.Bucket(); // Should fail because we can't create resources inflight | ^^^^^^^^^^^^^^^^^^ Cannot create preflight class \\"Bucket\\" in inflight phase error: Cannot qualify access to a lifted type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) - --> ../../../examples/tests/invalid/resource_inflight.w:4:7 + --> ../../../examples/tests/invalid/resource_inflight.main.w:4:7 | 4 | new cloud.Bucket(); // Should fail because we can't create resources inflight | ^^^^^^^^^^^^ Cannot qualify access to a lifted type \\"Bucket\\" (see https://github.com/winglang/wing/issues/76 for more details) @@ -2103,30 +2272,30 @@ Test Files 1 failed (1) Duration " `; -exports[`resource_init.w 1`] = ` +exports[`resource_init.main.w 1`] = ` "error: Multiple initializers defined in class R - --> ../../../examples/tests/invalid/resource_init.w:3:3 + --> ../../../examples/tests/invalid/resource_init.main.w:3:3 | 3 | init() {} | ^^^^^^^^^ Multiple initializers defined in class R error: Multiple inflight initializers defined in class R - --> ../../../examples/tests/invalid/resource_init.w:6:3 + --> ../../../examples/tests/invalid/resource_init.main.w:6:3 | 6 | inflight init() {} | ^^^^^^^^^^^^^^^^^^ Multiple inflight initializers defined in class R error: Multiple inflight initializers defined in class R - --> ../../../examples/tests/invalid/resource_init.w:9:3 + --> ../../../examples/tests/invalid/resource_init.main.w:9:3 | 9 | inflight init(x: num) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ Multiple inflight initializers defined in class R error: Inflight initializers cannot have parameters - --> ../../../examples/tests/invalid/resource_init.w:9:16 + --> ../../../examples/tests/invalid/resource_init.main.w:9:16 | 9 | inflight init(x: num) {} | ^^^^^^^^ Inflight initializers cannot have parameters @@ -2139,37 +2308,37 @@ Test Files 1 failed (1) Duration " `; -exports[`return_types.w 1`] = ` +exports[`return_types.main.w 1`] = ` "error: Return statement outside of function cannot return a value - --> ../../../examples/tests/invalid/return_types.w:1:5 + --> ../../../examples/tests/invalid/return_types.main.w:1:5 | 1 | return 9; | ^^^^^^^^^ Return statement outside of function cannot return a value error: Unexpected return value from void function. Return type annotations are required for methods. - --> ../../../examples/tests/invalid/return_types.w:19:5 + --> ../../../examples/tests/invalid/return_types.main.w:19:5 | 19 | return 9; | ^^^^^^^^^ Unexpected return value from void function. Return type annotations are required for methods. error: Unexpected return value from void function. Return type annotations are required for methods. - --> ../../../examples/tests/invalid/return_types.w:9:3 + --> ../../../examples/tests/invalid/return_types.main.w:9:3 | 9 | return 9; | ^^^^^^^^^ Unexpected return value from void function. Return type annotations are required for methods. error: Unexpected return value from void function. Return type annotations are required for methods. - --> ../../../examples/tests/invalid/return_types.w:12:5 + --> ../../../examples/tests/invalid/return_types.main.w:12:5 | 12 | return 9; | ^^^^^^^^^ Unexpected return value from void function. Return type annotations are required for methods. error: Return statement outside of function cannot return a value - --> ../../../examples/tests/invalid/return_types.w:4:5 + --> ../../../examples/tests/invalid/return_types.main.w:4:5 | 4 | return 9; | ^^^^^^^^^ Return statement outside of function cannot return a value @@ -2182,37 +2351,37 @@ Test Files 1 failed (1) Duration " `; -exports[`scope_and_id.w 1`] = ` +exports[`scope_and_id.main.w 1`] = ` "error: Expected type to be \\"str\\", but got \\"num\\" instead - --> ../../../examples/tests/invalid/scope_and_id.w:6:25 + --> ../../../examples/tests/invalid/scope_and_id.main.w:6:25 | 6 | new PreflightClass() as x; | ^ Expected type to be \\"str\\", but got \\"num\\" instead error: Expected scope to be a preflight object, instead found \\"num\\" - --> ../../../examples/tests/invalid/scope_and_id.w:8:1 + --> ../../../examples/tests/invalid/scope_and_id.main.w:8:1 | 8 | new PreflightClass() in x; | ^^^^^^^^^^^^^^^^^^^^^^^^^ Expected scope to be a preflight object, instead found \\"num\\" error: Inflight classes cannot have an id - --> ../../../examples/tests/invalid/scope_and_id.w:15:26 + --> ../../../examples/tests/invalid/scope_and_id.main.w:15:26 | 15 | new InflightClass() as \\"hi\\"; | ^^^^ Inflight classes cannot have an id error: Inflight classes cannot have a scope - --> ../../../examples/tests/invalid/scope_and_id.w:17:26 + --> ../../../examples/tests/invalid/scope_and_id.main.w:17:26 | 17 | new InflightClass() in pc; | ^^ Inflight classes cannot have a scope error: Cannot qualify access to a lifted object of type \\"PreflightClass\\" (see https://github.com/winglang/wing/issues/76 for more details) - --> ../../../examples/tests/invalid/scope_and_id.w:17:26 + --> ../../../examples/tests/invalid/scope_and_id.main.w:17:26 | 17 | new InflightClass() in pc; | ^^ Cannot qualify access to a lifted object of type \\"PreflightClass\\" (see https://github.com/winglang/wing/issues/76 for more details) @@ -2225,30 +2394,30 @@ Test Files 1 failed (1) Duration " `; -exports[`sorted_errors_no_span.w 1`] = ` +exports[`sorted_errors_no_span.main.w 1`] = ` "error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/sorted_errors_no_span.w:1:14 + --> ../../../examples/tests/invalid/sorted_errors_no_span.main.w:1:14 | 1 | let a: num = \\"s\\"; | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected \\"b\\" to be a type but it's a variable - --> ../../../examples/tests/invalid/sorted_errors_no_span.w:3:26 + --> ../../../examples/tests/invalid/sorted_errors_no_span.main.w:3:26 | 3 | inflight class c extends b {} | ^ Expected \\"b\\" to be a type but it's a variable error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/sorted_errors_no_span.w:4:14 + --> ../../../examples/tests/invalid/sorted_errors_no_span.main.w:4:14 | 4 | let d: num = \\"s\\"; | ^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected \\"b\\" to be a type but it's a variable - --> ../../../examples/tests/invalid/sorted_errors_no_span.w:5:26 + --> ../../../examples/tests/invalid/sorted_errors_no_span.main.w:5:26 | 5 | inflight class e extends b {} | ^ Expected \\"b\\" to be a type but it's a variable @@ -2261,30 +2430,30 @@ Test Files 1 failed (1) Duration " `; -exports[`statement_invalid_scope.w 1`] = ` +exports[`statement_invalid_scope.main.w 1`] = ` "error: Expected break statement to be inside of a loop (while/for) - --> ../../../examples/tests/invalid/statement_invalid_scope.w:3:5 + --> ../../../examples/tests/invalid/statement_invalid_scope.main.w:3:5 | 3 | break; | ^^^^^^ Expected break statement to be inside of a loop (while/for) error: Expected break statement to be inside of a loop (while/for) - --> ../../../examples/tests/invalid/statement_invalid_scope.w:7:5 + --> ../../../examples/tests/invalid/statement_invalid_scope.main.w:7:5 | 7 | break; | ^^^^^^ Expected break statement to be inside of a loop (while/for) error: Expected continue statement to be inside of a loop (while/for) - --> ../../../examples/tests/invalid/statement_invalid_scope.w:11:5 + --> ../../../examples/tests/invalid/statement_invalid_scope.main.w:11:5 | 11 | continue; | ^^^^^^^^^ Expected continue statement to be inside of a loop (while/for) error: Expected continue statement to be inside of a loop (while/for) - --> ../../../examples/tests/invalid/statement_invalid_scope.w:15:5 + --> ../../../examples/tests/invalid/statement_invalid_scope.main.w:15:5 | 15 | continue; | ^^^^^^^^^ Expected continue statement to be inside of a loop (while/for) @@ -2297,23 +2466,23 @@ Test Files 1 failed (1) Duration " `; -exports[`statements_if.w 1`] = ` +exports[`statements_if.main.w 1`] = ` "error: Unexpected unary operator \\"--\\" - --> ../../../examples/tests/invalid/statements_if.w:2:1 + --> ../../../examples/tests/invalid/statements_if.main.w:2:1 | 2 | --n; | ^^^ Unexpected unary operator \\"--\\" error: Expected type to be \\"bool\\", but got \\"num\\" instead - --> ../../../examples/tests/invalid/statements_if.w:5:5 + --> ../../../examples/tests/invalid/statements_if.main.w:5:5 | 5 | if !n {} | ^ Expected type to be \\"bool\\", but got \\"num\\" instead error: Expected type to be \\"bool\\", but got \\"num\\" instead - --> ../../../examples/tests/invalid/statements_if.w:8:5 + --> ../../../examples/tests/invalid/statements_if.main.w:8:5 | 8 | if !n || true {} | ^ Expected type to be \\"bool\\", but got \\"num\\" instead @@ -2326,9 +2495,9 @@ Test Files 1 failed (1) Duration " `; -exports[`std_containers.w 1`] = ` +exports[`std_containers.main.w 1`] = ` "error: Expected type to be \\"Array\\", but got \\"Array\\" instead - --> ../../../examples/tests/invalid/std_containers.w:3:18 + --> ../../../examples/tests/invalid/std_containers.main.w:3:18 | 3 | let c = a.concat(b); | ^ Expected type to be \\"Array\\", but got \\"Array\\" instead @@ -2341,37 +2510,37 @@ Test Files 1 failed (1) Duration " `; -exports[`struct_expansion.w 1`] = ` +exports[`struct_expansion.main.w 1`] = ` "error: Unexpected 'keyword_argument' - --> ../../../examples/tests/invalid/struct_expansion.w:11:15 + --> ../../../examples/tests/invalid/struct_expansion.main.w:11:15 | 11 | bucket1.put(file: \\"file.txt\\", \\"data\\"); | ^^^^^^^^^^^^^^^^ Unexpected 'keyword_argument' error: \\"bublic\\" is not a field of \\"BucketProps\\" - --> ../../../examples/tests/invalid/struct_expansion.w:3:15 + --> ../../../examples/tests/invalid/struct_expansion.main.w:3:15 | 3 | let bucket1 = new cloud.Bucket(bublic: false, public: true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \\"bublic\\" is not a field of \\"BucketProps\\" error: Expected between 0 and 1 arguments but got 2 - --> ../../../examples/tests/invalid/struct_expansion.w:7:15 + --> ../../../examples/tests/invalid/struct_expansion.main.w:7:15 | 7 | let bucket2 = new cloud.Bucket(2, public: true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Expected between 0 and 1 arguments but got 2 error: Expected type to be \\"BucketProps?\\", but got \\"num\\" instead - --> ../../../examples/tests/invalid/struct_expansion.w:7:32 + --> ../../../examples/tests/invalid/struct_expansion.main.w:7:32 | 7 | let bucket2 = new cloud.Bucket(2, public: true); | ^ Expected type to be \\"BucketProps?\\", but got \\"num\\" instead error: \\"status\\" is not initialized - --> ../../../examples/tests/invalid/struct_expansion.w:15:9 + --> ../../../examples/tests/invalid/struct_expansion.main.w:15:9 | 15 | let x = cloud.ApiResponse { | /---------^ @@ -2381,7 +2550,7 @@ error: \\"status\\" is not initialized error: \\"notAField\\" is not a field of \\"ApiResponse\\" - --> ../../../examples/tests/invalid/struct_expansion.w:20:9 + --> ../../../examples/tests/invalid/struct_expansion.main.w:20:9 | 20 | let y = cloud.ApiResponse { | /---------^ @@ -2393,7 +2562,7 @@ error: \\"notAField\\" is not a field of \\"ApiResponse\\" error: Expected 2 positional argument(s) but got 1 - --> ../../../examples/tests/invalid/struct_expansion.w:11:3 + --> ../../../examples/tests/invalid/struct_expansion.main.w:11:3 | 11 | bucket1.put(file: \\"file.txt\\", \\"data\\"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Expected 2 positional argument(s) but got 1 @@ -2406,23 +2575,23 @@ Test Files 1 failed (1) Duration " `; -exports[`struct_json_conversion.w 1`] = ` +exports[`struct_json_conversion.main.w 1`] = ` "error: Struct \\"A\\" contains field \\"b\\" which cannot be represented in Json - --> ../../../examples/tests/invalid/struct_json_conversion.w:8:3 + --> ../../../examples/tests/invalid/struct_json_conversion.main.w:8:3 | 8 | A.fromJson({}); | ^^^^^^^^ Struct \\"A\\" contains field \\"b\\" which cannot be represented in Json error: Struct \\"B\\" contains field \\"a\\" which cannot be represented in Json - --> ../../../examples/tests/invalid/struct_json_conversion.w:15:3 + --> ../../../examples/tests/invalid/struct_json_conversion.main.w:15:3 | 15 | B.fromJson({}); | ^^^^^^^^ Struct \\"B\\" contains field \\"a\\" which cannot be represented in Json error: Struct \\"C\\" contains field \\"b\\" which cannot be represented in Json - --> ../../../examples/tests/invalid/struct_json_conversion.w:22:3 + --> ../../../examples/tests/invalid/struct_json_conversion.main.w:22:3 | 22 | C.fromJson({}); | ^^^^^^^^ Struct \\"C\\" contains field \\"b\\" which cannot be represented in Json @@ -2435,51 +2604,51 @@ Test Files 1 failed (1) Duration " `; -exports[`structs.w 1`] = ` +exports[`structs.main.w 1`] = ` "error: Struct \\"C\\" extends \\"B\\" which introduces a conflicting member \\"x\\" (str != str) - --> ../../../examples/tests/invalid/structs.w:11:8 + --> ../../../examples/tests/invalid/structs.main.w:11:8 | 11 | struct C extends B { | ^ Struct \\"C\\" extends \\"B\\" which introduces a conflicting member \\"x\\" (str != str) error: \\"x\\" is not initialized - --> ../../../examples/tests/invalid/structs.w:16:18 + --> ../../../examples/tests/invalid/structs.main.w:16:18 | 16 | let someStruct = B { y: 5 }; | ^^^^^^^^^^ \\"x\\" is not initialized error: Struct fields must have immutable types - --> ../../../examples/tests/invalid/structs.w:20:3 + --> ../../../examples/tests/invalid/structs.main.w:20:3 | 20 | f: MutArray; | ^ Struct fields must have immutable types error: Struct fields must have immutable types - --> ../../../examples/tests/invalid/structs.w:25:3 + --> ../../../examples/tests/invalid/structs.main.w:25:3 | 25 | f: Map>>; | ^ Struct fields must have immutable types error: Unknown symbol \\"badField\\" - --> ../../../examples/tests/invalid/structs.w:32:7 + --> ../../../examples/tests/invalid/structs.main.w:32:7 | 32 | log(a.badField); | ^^^^^^^^ Unknown symbol \\"badField\\" error: Struct \\"Showtime\\" extends \\"Dazzle\\" which introduces a conflicting member \\"a\\" (num != num) - --> ../../../examples/tests/invalid/structs.w:44:8 + --> ../../../examples/tests/invalid/structs.main.w:44:8 | 44 | struct Showtime extends Razzle, Dazzle {} | ^^^^^^^^ Struct \\"Showtime\\" extends \\"Dazzle\\" which introduces a conflicting member \\"a\\" (num != num) error: Cannot instantiate type \\"BucketProps\\" because it is a struct and not a class. Use struct instantiation instead. - --> ../../../examples/tests/invalid/structs.w:47:13 + --> ../../../examples/tests/invalid/structs.main.w:47:13 | 47 | let x = new cloud.BucketProps(1); | ^^^^^^^^^^^^^^^^^ Cannot instantiate type \\"BucketProps\\" because it is a struct and not a class. Use struct instantiation instead. @@ -2492,44 +2661,51 @@ Test Files 1 failed (1) Duration " `; -exports[`super_call.w 1`] = ` +exports[`super_call.main.w 1`] = ` "error: \\"super\\" can only be used inside of classes - --> ../../../examples/tests/invalid/super_call.w:32:7 + --> ../../../examples/tests/invalid/super_call.main.w:32:7 | 32 | super.do(); | ^^ \\"super\\" can only be used inside of classes +error: Cannot override private method \\"m1\\" of \\"BaseClass\\" + --> ../../../examples/tests/invalid/super_call.main.w:47:12 + | +47 | inflight m1(): str { + | ^^ Cannot override private method \\"m1\\" of \\"BaseClass\\" + + error: \`super\` calls inside inflight closures not supported yet, see: https://github.com/winglang/wing/issues/3474 - --> ../../../examples/tests/invalid/super_call.w:52:50 + --> ../../../examples/tests/invalid/super_call.main.w:52:50 | 52 | return \\"this: \${this.m1()}, super: \${super.m1()}\\"; | ^^ \`super\` calls inside inflight closures not supported yet, see: https://github.com/winglang/wing/issues/3474 error: Cannot call super method inside of a static method - --> ../../../examples/tests/invalid/super_call.w:26:11 + --> ../../../examples/tests/invalid/super_call.main.w:26:11 | 26 | super.method(); | ^^^^^^ Cannot call super method inside of a static method error: super class \\"A\\" does not have a method named \\"child_method\\" - --> ../../../examples/tests/invalid/super_call.w:20:11 + --> ../../../examples/tests/invalid/super_call.main.w:20:11 | 20 | super.child_method(); | ^^^^^^^^^^^^ super class \\"A\\" does not have a method named \\"child_method\\" error: Cannot call super method because class InflightA has no parent - --> ../../../examples/tests/invalid/super_call.w:12:11 + --> ../../../examples/tests/invalid/super_call.main.w:12:11 | 12 | super.method(); | ^^^^^^ Cannot call super method because class InflightA has no parent error: Cannot call super method because class A has no parent - --> ../../../examples/tests/invalid/super_call.w:4:11 + --> ../../../examples/tests/invalid/super_call.main.w:4:11 | 4 | super.method(); | ^^^^^^ Cannot call super method because class A has no parent @@ -2542,9 +2718,9 @@ Test Files 1 failed (1) Duration " `; -exports[`throw_non_string.w 1`] = ` +exports[`throw_non_string.main.w 1`] = ` "error: Expected type to be \\"str\\", but got \\"num\\" instead - --> ../../../examples/tests/invalid/throw_non_string.w:1:7 + --> ../../../examples/tests/invalid/throw_non_string.main.w:1:7 | 1 | throw 42; | ^^ Expected type to be \\"str\\", but got \\"num\\" instead @@ -2557,9 +2733,9 @@ Test Files 1 failed (1) Duration " `; -exports[`try_no_catch_or_finally.w 1`] = ` +exports[`try_no_catch_or_finally.main.w 1`] = ` "error: Missing \`catch\` or \`finally\` blocks for this try statement - --> ../../../examples/tests/invalid/try_no_catch_or_finally.w:1:1 + --> ../../../examples/tests/invalid/try_no_catch_or_finally.main.w:1:1 | 1 | / try { 2 | | log(\\"Hello World\\"); @@ -2574,23 +2750,23 @@ Test Files 1 failed (1) Duration " `; -exports[`types_strings_arithmetic.w 1`] = ` +exports[`types_strings_arithmetic.main.w 1`] = ` "error: Binary operator '+' cannot be applied to operands of type 'num' and 'str'; only (num, num) and (str, str) are supported - --> ../../../examples/tests/invalid/types_strings_arithmetic.w:1:10 + --> ../../../examples/tests/invalid/types_strings_arithmetic.main.w:1:10 | 1 | let e1 = 2 + \\"2\\"; | ^^^^^^^ Binary operator '+' cannot be applied to operands of type 'num' and 'str'; only (num, num) and (str, str) are supported error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/types_strings_arithmetic.w:4:10 + --> ../../../examples/tests/invalid/types_strings_arithmetic.main.w:4:10 | 4 | let e2 = 2 == \\"2\\"; | ^^^^^^^^ Expected type to be \\"num\\", but got \\"str\\" instead error: Expected type to be \\"num\\", but got \\"str\\" instead - --> ../../../examples/tests/invalid/types_strings_arithmetic.w:10:10 + --> ../../../examples/tests/invalid/types_strings_arithmetic.main.w:10:10 | 10 | let e3 = \\"\${strExample}!\\" * numExample; | ^^^^^^^^^^^^^^^^ Expected type to be \\"num\\", but got \\"str\\" instead @@ -2603,37 +2779,37 @@ Test Files 1 failed (1) Duration " `; -exports[`unimplemented_grammar.w 1`] = ` +exports[`unimplemented_grammar.main.w 1`] = ` "error: builtin \\"any\\" is not supported yet - see https://github.com/winglang/wing/issues/434 - --> ../../../examples/tests/invalid/unimplemented_grammar.w:1:8 + --> ../../../examples/tests/invalid/unimplemented_grammar.main.w:1:8 | 1 | let b: any = 0; | ^^^ builtin \\"any\\" is not supported yet - see https://github.com/winglang/wing/issues/434 error: builtin container type \\"Promise\\" is not supported yet - see https://github.com/winglang/wing/issues/529 - --> ../../../examples/tests/invalid/unimplemented_grammar.w:2:19 + --> ../../../examples/tests/invalid/unimplemented_grammar.main.w:2:19 | 2 | let somePromise = Promise{}; | ^^^^^^^^^^^^ builtin container type \\"Promise\\" is not supported yet - see https://github.com/winglang/wing/issues/529 error: expression \\"defer_expression\\" is not supported yet - see https://github.com/winglang/wing/issues/116 - --> ../../../examples/tests/invalid/unimplemented_grammar.w:3:9 + --> ../../../examples/tests/invalid/unimplemented_grammar.main.w:3:9 | 3 | let c = defer somePromise(); | ^^^^^^^^^^^^^^^^^^^ expression \\"defer_expression\\" is not supported yet - see https://github.com/winglang/wing/issues/116 error: expression \\"await_expression\\" is not supported yet - see https://github.com/winglang/wing/issues/116 - --> ../../../examples/tests/invalid/unimplemented_grammar.w:4:9 + --> ../../../examples/tests/invalid/unimplemented_grammar.main.w:4:9 | 4 | let d = await c; | ^^^^^^^ expression \\"await_expression\\" is not supported yet - see https://github.com/winglang/wing/issues/116 error: Unable to infer type - --> ../../../examples/tests/invalid/unimplemented_grammar.w:2:5 + --> ../../../examples/tests/invalid/unimplemented_grammar.main.w:2:5 | 2 | let somePromise = Promise{}; | ^^^^^^^^^^^ Unable to infer type @@ -2646,9 +2822,9 @@ Test Files 1 failed (1) Duration " `; -exports[`unknown_field.w 1`] = ` +exports[`unknown_field.main.w 1`] = ` "error: Unknown symbol \\"a\\" - --> ../../../examples/tests/invalid/unknown_field.w:1:12 + --> ../../../examples/tests/invalid/unknown_field.main.w:1:12 | 1 | std.String.a.b.c.fromJson(); | ^ Unknown symbol \\"a\\" @@ -2661,9 +2837,9 @@ Test Files 1 failed (1) Duration " `; -exports[`unknown_submodule.w 1`] = ` +exports[`unknown_submodule.main.w 1`] = ` "error: Expected identifier \\"std\\" to be a variable, but it's a namespace - --> ../../../examples/tests/invalid/unknown_submodule.w:1:1 + --> ../../../examples/tests/invalid/unknown_submodule.main.w:1:1 | 1 | std.random.String.fromJson(\\"hello\\"); | ^^^ Expected identifier \\"std\\" to be a variable, but it's a namespace @@ -2676,65 +2852,65 @@ Test Files 1 failed (1) Duration " `; -exports[`unknown_symbol.w 1`] = ` +exports[`unknown_symbol.main.w 1`] = ` "error: Reserved word - --> ../../../examples/tests/invalid/unknown_symbol.w:35:5 + --> ../../../examples/tests/invalid/unknown_symbol.main.w:35:5 | 35 | let let = 2; | ^^^ Reserved word error: Unknown symbol \\"clod\\" - --> ../../../examples/tests/invalid/unknown_symbol.w:3:18 + --> ../../../examples/tests/invalid/unknown_symbol.main.w:3:18 | 3 | let bucket = new clod.Bucket(); | ^^^^ Unknown symbol \\"clod\\" error: Unknown symbol \\"cloudy\\" - --> ../../../examples/tests/invalid/unknown_symbol.w:6:17 + --> ../../../examples/tests/invalid/unknown_symbol.main.w:6:17 | 6 | let funky = new cloudy.Funktion(inflight () => { }); | ^^^^^^ Unknown symbol \\"cloudy\\" error: Unknown symbol \\"y\\" - --> ../../../examples/tests/invalid/unknown_symbol.w:9:13 + --> ../../../examples/tests/invalid/unknown_symbol.main.w:9:13 | 9 | let x = 2 + y; | ^ Unknown symbol \\"y\\" error: Unknown symbol \\"B\\" - --> ../../../examples/tests/invalid/unknown_symbol.w:28:17 + --> ../../../examples/tests/invalid/unknown_symbol.main.w:28:17 | 28 | class A extends B { | ^ Unknown symbol \\"B\\" error: Unknown symbol \\"unknown\\" - --> ../../../examples/tests/invalid/unknown_symbol.w:32:1 + --> ../../../examples/tests/invalid/unknown_symbol.main.w:32:1 | 32 | unknown = 1; | ^^^^^^^ Unknown symbol \\"unknown\\" error: Unknown symbol \\"assert\\" - --> ../../../examples/tests/invalid/unknown_symbol.w:20:17 + --> ../../../examples/tests/invalid/unknown_symbol.main.w:20:17 | 20 | this.bucket.assert(2 + \\"2\\"); | ^^^^^^ Unknown symbol \\"assert\\" error: Binary operator '+' cannot be applied to operands of type 'num' and 'str'; only (num, num) and (str, str) are supported - --> ../../../examples/tests/invalid/unknown_symbol.w:20:24 + --> ../../../examples/tests/invalid/unknown_symbol.main.w:20:24 | 20 | this.bucket.assert(2 + \\"2\\"); | ^^^^^^^ Binary operator '+' cannot be applied to operands of type 'num' and 'str'; only (num, num) and (str, str) are supported error: Unknown symbol \\"methodWhichIsNotPartOfBucketApi\\" - --> ../../../examples/tests/invalid/unknown_symbol.w:23:24 + --> ../../../examples/tests/invalid/unknown_symbol.main.w:23:24 | 23 | return this.bucket.methodWhichIsNotPartOfBucketApi(id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unknown symbol \\"methodWhichIsNotPartOfBucketApi\\" @@ -2747,16 +2923,16 @@ Test Files 1 failed (1) Duration " `; -exports[`use_before_defined.w 1`] = ` +exports[`use_before_defined.main.w 1`] = ` "error: Unknown symbol \\"y\\" - --> ../../../examples/tests/invalid/use_before_defined.w:1:8 + --> ../../../examples/tests/invalid/use_before_defined.main.w:1:8 | 1 | log(\\"\${y}\\"); // Access y before it's defined | ^ Unknown symbol \\"y\\" error: Symbol \\"x\\" used before being defined - --> ../../../examples/tests/invalid/use_before_defined.w:5:10 + --> ../../../examples/tests/invalid/use_before_defined.main.w:5:10 | 5 | log(\\"\${x}\\"); | ^ Symbol \\"x\\" used before being defined @@ -2769,9 +2945,9 @@ Test Files 1 failed (1) Duration " `; -exports[`variable_scoping.w 1`] = ` +exports[`variable_scoping.main.w 1`] = ` "error: Unknown symbol \\"x\\" - --> ../../../examples/tests/invalid/variable_scoping.w:6:11 + --> ../../../examples/tests/invalid/variable_scoping.main.w:6:11 | 6 | let z = x; | ^ Unknown symbol \\"x\\" @@ -2784,16 +2960,16 @@ Test Files 1 failed (1) Duration " `; -exports[`void_in_expression_position.w 1`] = ` +exports[`void_in_expression_position.main.w 1`] = ` "error: Property not found - --> ../../../examples/tests/invalid/void_in_expression_position.w:1:12 + --> ../../../examples/tests/invalid/void_in_expression_position.main.w:1:12 | 1 | log(\\"hey\\").get(\\"x\\"); | ^^^ Property not found error: Binary operator '+' cannot be applied to operands of type 'num' and 'void'; only (num, num) and (str, str) are supported - --> ../../../examples/tests/invalid/void_in_expression_position.w:7:9 + --> ../../../examples/tests/invalid/void_in_expression_position.main.w:7:9 | 7 | let y = 5 + log(\\"hello\\"); | ^^^^^^^^^^^^^^^^ Binary operator '+' cannot be applied to operands of type 'num' and 'void'; only (num, num) and (str, str) are supported From 2870580760b53f729e85d64e9c224c1cb602ec15 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 14 Sep 2023 12:04:35 +0300 Subject: [PATCH 48/56] fixed tests --- examples/tests/valid/dynamo.main.w | 2 +- examples/tests/valid/dynamo_awscdk.main.w | 2 +- examples/tests/valid/impl_interface.main.w | 2 +- examples/tests/valid/super_call.main.w | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/tests/valid/dynamo.main.w b/examples/tests/valid/dynamo.main.w index 06b3f606fa9..b73a6b98e23 100644 --- a/examples/tests/valid/dynamo.main.w +++ b/examples/tests/valid/dynamo.main.w @@ -42,7 +42,7 @@ class DynamoTable { this.tableName = this.table.name; } - bind(host: std.IInflightHost, ops: Array) { + public bind(host: std.IInflightHost, ops: Array) { if let host = aws.Function.from(host) { if ops.contains("putItem") { host.addPolicyStatements([aws.PolicyStatement { diff --git a/examples/tests/valid/dynamo_awscdk.main.w b/examples/tests/valid/dynamo_awscdk.main.w index c472e59a187..95abc3de0e9 100644 --- a/examples/tests/valid/dynamo_awscdk.main.w +++ b/examples/tests/valid/dynamo_awscdk.main.w @@ -40,7 +40,7 @@ class DynamoTable { this.tableName = this.table.tableName; } - bind(host: std.IInflightHost, ops: Array) { + public bind(host: std.IInflightHost, ops: Array) { if let host = aws.Function.from(host) { if ops.contains("putItem") { host.addPolicyStatements([aws.PolicyStatement { diff --git a/examples/tests/valid/impl_interface.main.w b/examples/tests/valid/impl_interface.main.w index 0961ce6d6a2..7e19198894e 100644 --- a/examples/tests/valid/impl_interface.main.w +++ b/examples/tests/valid/impl_interface.main.w @@ -51,7 +51,7 @@ let z: IAnimal = new Dog(); // base class is checked for implemention of interface class Terrier extends Dog { - inflight eat() { + public inflight eat() { return; } } diff --git a/examples/tests/valid/super_call.main.w b/examples/tests/valid/super_call.main.w index 17cfce8a58e..ccda239565f 100644 --- a/examples/tests/valid/super_call.main.w +++ b/examples/tests/valid/super_call.main.w @@ -7,13 +7,13 @@ class A { } class B extends A { - description(): str { + public description(): str { return "B"; } } class C extends B { - description(): str { + public description(): str { return "C extends ${super.description()}"; } } @@ -33,7 +33,7 @@ let e = new E(); assert(e.description() == "E extends C extends B"); inflight class InflightA { - description(): str { + public description(): str { return "InflightA"; } } @@ -54,7 +54,7 @@ test "super call inflight" { bring cloud; let b = new cloud.Bucket(); class BaseClass { - inflight do(): str { + public inflight do(): str { return b.get("k"); // BaseClass class required read acceess to b } } From 21481d6d13f570ecc1de2f89f6099c9133d75ee3 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 14 Sep 2023 12:10:17 +0300 Subject: [PATCH 49/56] rename test files to be main --- .../tests/invalid/{access_modifiers.w => access_modifiers.main.w} | 0 .../{jsii_access_modifiers.w => jsii_access_modifiers.main.w} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename examples/tests/invalid/{access_modifiers.w => access_modifiers.main.w} (100%) rename examples/tests/invalid/{jsii_access_modifiers.w => jsii_access_modifiers.main.w} (100%) diff --git a/examples/tests/invalid/access_modifiers.w b/examples/tests/invalid/access_modifiers.main.w similarity index 100% rename from examples/tests/invalid/access_modifiers.w rename to examples/tests/invalid/access_modifiers.main.w diff --git a/examples/tests/invalid/jsii_access_modifiers.w b/examples/tests/invalid/jsii_access_modifiers.main.w similarity index 100% rename from examples/tests/invalid/jsii_access_modifiers.w rename to examples/tests/invalid/jsii_access_modifiers.main.w From b64fda45dc0d56e849b5b4cf4e538f95e52f2e42 Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Thu, 14 Sep 2023 09:25:45 +0000 Subject: [PATCH 50/56] chore: self mutation (build.diff) Signed-off-by: monada-bot[bot] --- libs/wingsdk/src/.gen/versions.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/wingsdk/src/.gen/versions.json b/libs/wingsdk/src/.gen/versions.json index e69de29bb2d..fbe6adcd3fd 100644 --- a/libs/wingsdk/src/.gen/versions.json +++ b/libs/wingsdk/src/.gen/versions.json @@ -0,0 +1,6 @@ +{ + "registry.terraform.io/hashicorp/random": "3.5.1", + "registry.terraform.io/hashicorp/google": "4.63.1", + "registry.terraform.io/hashicorp/azurerm": "3.54.0", + "registry.terraform.io/hashicorp/aws": "4.65.0" +} From fa03bed230dddb03bbf83fe3fc8296fd7bd4da07 Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Thu, 14 Sep 2023 09:25:46 +0000 Subject: [PATCH 51/56] chore: self mutation (e2e-2of2.diff) Signed-off-by: monada-bot[bot] --- tools/hangar/__snapshots__/invalid.ts.snap | 134 +++++---------------- 1 file changed, 32 insertions(+), 102 deletions(-) diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 7232d910bc2..755c6ff2983 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -15,240 +15,191 @@ Test Files 1 failed (1) Duration " `; -exports[`access_modifiers.w 1`] = ` -"error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - --> ../../../examples/tests/invalid/access_modifiers.w:98:1 - | -98 | let foo = new Foo(); - | ^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - - -error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - --> ../../../examples/tests/invalid/access_modifiers.w:100:1 - | -100 | log(foo.protected_field); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - - -error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - --> ../../../examples/tests/invalid/access_modifiers.w:102:1 - | -102 | log(foo.private_field); - | ^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - - -error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - --> ../../../examples/tests/invalid/access_modifiers.w:104:1 - | -104 | log(foo.public_field); - | ^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - - -error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - --> ../../../examples/tests/invalid/access_modifiers.w:105:1 - | -105 | Foo.public_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - - -error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - --> ../../../examples/tests/invalid/access_modifiers.w:106:1 - | -106 | Foo.protected_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - - -error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - --> ../../../examples/tests/invalid/access_modifiers.w:108:1 - | -108 | Foo.private_static_method(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - - -error: Method \\"private_method\\" is private in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. - --> ../../../examples/tests/invalid/access_modifiers.w:40:3 +exports[`access_modifiers.main.w 1`] = ` +"error: Method \\"private_method\\" is private in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. + --> ../../../examples/tests/invalid/access_modifiers.main.w:40:3 | 40 | private_method() {} | ^^^^^^^^^^^^^^ Method \\"private_method\\" is private in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. error: Method \\"protected_method\\" is protected in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. - --> ../../../examples/tests/invalid/access_modifiers.w:38:13 + --> ../../../examples/tests/invalid/access_modifiers.main.w:38:13 | 38 | protected protected_method() {} | ^^^^^^^^^^^^^^^^ Method \\"protected_method\\" is protected in \\"Foo\\" but it's an implementation of \\"SomeInterface\\". Interface members must be public. error: Cannot override private method \\"method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:49:3 + --> ../../../examples/tests/invalid/access_modifiers.main.w:49:3 | 49 | method() { | ^^^^^^ Cannot override private method \\"method\\" of \\"Foo\\" error: Cannot override private method \\"method\\" of \\"Bar\\" - --> ../../../examples/tests/invalid/access_modifiers.w:72:3 + --> ../../../examples/tests/invalid/access_modifiers.main.w:72:3 | 72 | method() { | ^^^^^^ Cannot override private method \\"method\\" of \\"Bar\\" error: Cannot access protected member \\"protected_field\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:100:9 + --> ../../../examples/tests/invalid/access_modifiers.main.w:100:9 | 100 | log(foo.protected_field); | ^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_field\\" of \\"Foo\\" error: Cannot access private member \\"private_field\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:102:9 + --> ../../../examples/tests/invalid/access_modifiers.main.w:102:9 | 102 | log(foo.private_field); | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Foo\\" error: Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:106:5 + --> ../../../examples/tests/invalid/access_modifiers.main.w:106:5 | 106 | Foo.protected_static_method(); | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:108:5 + --> ../../../examples/tests/invalid/access_modifiers.main.w:108:5 | 108 | Foo.private_static_method(); | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" error: Cannot override public method \\"public_method\\" of \\"Foo\\" with a private method - --> ../../../examples/tests/invalid/access_modifiers.w:148:3 + --> ../../../examples/tests/invalid/access_modifiers.main.w:148:3 | 148 | public_method() {} | ^^^^^^^^^^^^^ Cannot override public method \\"public_method\\" of \\"Foo\\" with a private method error: Cannot override protected method \\"protected_method\\" of \\"Foo\\" with a private method - --> ../../../examples/tests/invalid/access_modifiers.w:150:3 + --> ../../../examples/tests/invalid/access_modifiers.main.w:150:3 | 150 | protected_method() {} | ^^^^^^^^^^^^^^^^ Cannot override protected method \\"protected_method\\" of \\"Foo\\" with a private method error: Cannot override private method \\"private_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:152:3 + --> ../../../examples/tests/invalid/access_modifiers.main.w:152:3 | 152 | private_method() {} | ^^^^^^^^^^^^^^ Cannot override private method \\"private_method\\" of \\"Foo\\" error: Cannot override public method \\"public_method\\" of \\"Foo\\" with a protected method - --> ../../../examples/tests/invalid/access_modifiers.w:157:13 + --> ../../../examples/tests/invalid/access_modifiers.main.w:157:13 | 157 | protected public_method() {} | ^^^^^^^^^^^^^ Cannot override public method \\"public_method\\" of \\"Foo\\" with a protected method error: Cannot override private method \\"private_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:160:13 + --> ../../../examples/tests/invalid/access_modifiers.main.w:160:13 | 160 | protected private_method() {} | ^^^^^^^^^^^^^^ Cannot override private method \\"private_method\\" of \\"Foo\\" error: Cannot override private method \\"private_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:167:10 + --> ../../../examples/tests/invalid/access_modifiers.main.w:167:10 | 167 | public private_method() {} | ^^^^^^^^^^^^^^ Cannot override private method \\"private_method\\" of \\"Foo\\" error: Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:128:9 + --> ../../../examples/tests/invalid/access_modifiers.main.w:128:9 | 128 | Foo.protected_static_method(); | ^^^^^^^^^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:130:9 + --> ../../../examples/tests/invalid/access_modifiers.main.w:130:9 | 130 | Foo.private_static_method(); | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" error: Cannot access protected member \\"protected_field\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:114:13 + --> ../../../examples/tests/invalid/access_modifiers.main.w:114:13 | 114 | log(foo.protected_field); | ^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_field\\" of \\"Foo\\" error: Cannot access private member \\"private_field\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:116:13 + --> ../../../examples/tests/invalid/access_modifiers.main.w:116:13 | 116 | log(foo.private_field); | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Foo\\" error: Cannot access protected member \\"protected_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:120:9 + --> ../../../examples/tests/invalid/access_modifiers.main.w:120:9 | 120 | foo.protected_method(); | ^^^^^^^^^^^^^^^^ Cannot access protected member \\"protected_method\\" of \\"Foo\\" error: Cannot access private member \\"private_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:122:9 + --> ../../../examples/tests/invalid/access_modifiers.main.w:122:9 | 122 | foo.private_method(); | ^^^^^^^^^^^^^^ Cannot access private member \\"private_method\\" of \\"Foo\\" error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:88:9 + --> ../../../examples/tests/invalid/access_modifiers.main.w:88:9 | 88 | Foo.private_static_method(); | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" error: Cannot access private member \\"private_static_method\\" of \\"Bar\\" - --> ../../../examples/tests/invalid/access_modifiers.w:93:9 + --> ../../../examples/tests/invalid/access_modifiers.main.w:93:9 | 93 | Bar.private_static_method(); | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Bar\\" error: Cannot access private member \\"private_field\\" of \\"Baz\\" - --> ../../../examples/tests/invalid/access_modifiers.w:75:14 + --> ../../../examples/tests/invalid/access_modifiers.main.w:75:14 | 75 | log(this.private_field); | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Baz\\" error: Cannot access private member \\"private_method\\" of \\"Baz\\" - --> ../../../examples/tests/invalid/access_modifiers.w:80:10 + --> ../../../examples/tests/invalid/access_modifiers.main.w:80:10 | 80 | this.private_method(); | ^^^^^^^^^^^^^^ Cannot access private member \\"private_method\\" of \\"Baz\\" error: Cannot access private member \\"private_static_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.w:65:9 + --> ../../../examples/tests/invalid/access_modifiers.main.w:65:9 | 65 | Foo.private_static_method(); | ^^^^^^^^^^^^^^^^^^^^^ Cannot access private member \\"private_static_method\\" of \\"Foo\\" error: Cannot access private member \\"private_field\\" of \\"Bar\\" - --> ../../../examples/tests/invalid/access_modifiers.w:52:14 + --> ../../../examples/tests/invalid/access_modifiers.main.w:52:14 | 52 | log(this.private_field); | ^^^^^^^^^^^^^ Cannot access private member \\"private_field\\" of \\"Bar\\" error: Cannot access private member \\"private_method\\" of \\"Bar\\" - --> ../../../examples/tests/invalid/access_modifiers.w:57:10 + --> ../../../examples/tests/invalid/access_modifiers.main.w:57:10 | 57 | this.private_method(); | ^^^^^^^^^^^^^^ Cannot access private member \\"private_method\\" of \\"Bar\\" @@ -1636,30 +1587,9 @@ Test Files 1 failed (1) Duration " `; -exports[`jsii_access_modifiers.w 1`] = ` -"error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - --> ../../../examples/tests/invalid/jsii_access_modifiers.w:4:1 - | -4 | let b = new cloud.Bucket(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - - -error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - --> ../../../examples/tests/invalid/jsii_access_modifiers.w:13:1 - | -13 | b.createTopic(cloud.BucketEventType.CREATE); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - - -error: Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - --> ../../../examples/tests/invalid/jsii_access_modifiers.w:17:1 - | -17 | b.addObject(\\"k\\", \\"v\\"); - | ^^^^^^^^^^^^^^^^^^^^^^ Module files cannot have statements besides classes, interfaces, enums, and structs. Rename the file to end with \`.main.w\` to make this an entrypoint file. - - -error: Cannot access protected member \\"createTopic\\" of \\"Bucket\\" - --> ../../../examples/tests/invalid/jsii_access_modifiers.w:13:3 +exports[`jsii_access_modifiers.main.w 1`] = ` +"error: Cannot access protected member \\"createTopic\\" of \\"Bucket\\" + --> ../../../examples/tests/invalid/jsii_access_modifiers.main.w:13:3 | 13 | b.createTopic(cloud.BucketEventType.CREATE); | ^^^^^^^^^^^ Cannot access protected member \\"createTopic\\" of \\"Bucket\\" From 11ed9d4c289a977b0cf0452c98b428b4a6e9c516 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 14 Sep 2023 17:16:22 +0300 Subject: [PATCH 52/56] `public` -> `pub` --- docs/docs/03-language-reference.md | 24 ++++---- docs/docs/07-examples/08-classes.md | 16 ++--- examples/proposed/cacheable-function.w | 2 +- examples/proposed/counting-semaphore.w | 8 +-- .../tests/invalid/access_modifiers.main.w | 12 ++-- .../access_static_from_instance.main.w | 4 +- .../call_inflight_from_preflight.main.w | 2 +- examples/tests/invalid/impl_interface.main.w | 2 +- ...t_class_interface_structural_typing.main.w | 2 +- .../invalid/inflight_ref_explicit_ops.main.w | 12 ++-- .../inflight_ref_resource_sub_method.main.w | 6 +- .../invalid/inflight_ref_unknown_op.main.w | 2 +- examples/tests/invalid/nil.main.w | 2 +- .../invalid/preflight_from_inflight.main.w | 2 +- .../reassign_to_nonreassignable.main.w | 2 +- .../resource_access_field_as_method.main.w | 2 +- .../tests/sdk_tests/function/logging.main.w | 2 +- .../tests/sdk_tests/queue/set_consumer.main.w | 2 +- .../tests/sdk_tests/topic/on_message.main.w | 2 +- examples/tests/sdk_tests/util/sleep.main.w | 2 +- examples/tests/sdk_tests/util/uuidv4.main.w | 4 +- .../tests/sdk_tests/util/wait-until.main.w | 2 +- .../tests/sdk_tests/website/website.main.w | 2 +- examples/tests/valid/assertions.w | 6 +- examples/tests/valid/baz.w | 2 +- examples/tests/valid/bring_local.main.w | 2 +- .../tests/valid/call_static_of_myself.main.w | 10 ++-- .../valid/calling_inflight_variants.main.w | 4 +- .../capture_reassigable_class_field.main.w | 6 +- .../capture_resource_with_no_inflight.main.w | 4 +- examples/tests/valid/capture_tokens.main.w | 4 +- examples/tests/valid/class.main.w | 22 +++---- examples/tests/valid/closure_class.main.w | 2 +- examples/tests/valid/double_reference.main.w | 6 +- examples/tests/valid/doubler.main.w | 2 +- examples/tests/valid/dynamo.main.w | 4 +- examples/tests/valid/dynamo_awscdk.main.w | 6 +- .../tests/valid/extern_implementation.main.w | 8 +-- examples/tests/valid/impl_interface.main.w | 12 ++-- .../valid/inflight_capture_static.main.w | 6 +- .../inflight_class_as_struct_members.main.w | 2 +- .../valid/inflight_class_capture_const.main.w | 2 +- .../valid/inflight_class_definitions.main.w | 16 ++--- ...nflight_class_inner_capture_mutable.main.w | 2 +- ...light_class_inside_inflight_closure.main.w | 6 +- ...ight_class_outside_inflight_closure.main.w | 2 +- ...t_class_structural_interace_handler.main.w | 2 +- .../valid/inflights_calling_inflights.main.w | 2 +- examples/tests/valid/json.main.w | 2 +- .../tests/valid/lift_expr_with_this.main.w | 2 +- examples/tests/valid/lift_this.main.w | 2 +- examples/tests/valid/lift_via_closure.main.w | 4 +- examples/tests/valid/nil.main.w | 6 +- examples/tests/valid/optionals.main.w | 8 +-- examples/tests/valid/reassignment.main.w | 4 +- examples/tests/valid/resource.main.w | 18 +++--- .../valid/resource_as_inflight_literal.main.w | 2 +- .../tests/valid/resource_call_static.main.w | 2 +- examples/tests/valid/resource_captures.main.w | 32 +++++----- .../valid/resource_captures_globals.main.w | 14 ++--- examples/tests/valid/static_members.main.w | 8 +-- examples/tests/valid/store.w | 2 +- examples/tests/valid/subdir/bar.w | 2 +- examples/tests/valid/subdir/foo.w | 6 +- examples/tests/valid/super_call.main.w | 14 ++--- libs/tree-sitter-wing/grammar.js | 2 +- .../corpus/statements/class_and_resource.txt | 6 +- libs/wingc/src/jsify/tests.rs | 58 +++++++++---------- libs/wingc/src/parser.rs | 4 +- libs/wingsdk/src/.gen/versions.json | 6 ++ 70 files changed, 233 insertions(+), 227 deletions(-) diff --git a/docs/docs/03-language-reference.md b/docs/docs/03-language-reference.md index e6bf00f11a6..223e6ba3b24 100644 --- a/docs/docs/03-language-reference.md +++ b/docs/docs/03-language-reference.md @@ -687,17 +687,17 @@ class Bar extends Foo { } } ``` -The `public` access modifier makes the class member accessible from anywhere. +The `pub` access modifier makes the class member accessible from anywhere. Interface members are always public. -Implementing interface members in a class requires explicitly flagging them as `public`. +Implementing interface members in a class requires explicitly flagging them as `pub`. ```TS interface FooInterface { - public interface_method(): void; // Interface definitions are always implicitly `public` + interface_method(): void; // Interface definitions are always implicitly `pub` } class Foo impl FooInterface { - public public_method() {} // This can be accessed from outside of the class implemenetation - public interface_method() {} // This must be explicitly defined as `public` since it's an interface implementation + pub public_method() {} // This can be accessed from outside of the class implemenetation + pub interface_method() {} // This must be explicitly defined as `pub` since it's an interface implementation } let f = new Foo(); f.public_method(); // We can call this method from outside the class - it's public @@ -708,12 +708,12 @@ Struct fields are always public and do not have access modifiers. #### 1.5.1 Method overriding and access modifiers Private methods cannot be overriden. -Overriding a method of a parent class requires the parent class's method to be either `public` or `protected`. +Overriding a method of a parent class requires the parent class's method to be either `pub` or `protected`. The overriding method can have either the same access modifier as the original method or a more permissive one. You cannot "decrease" the access level down the inheritence hierarchy, only "increase" it. In practice this means: -* `protected` methods can be overidden by either a `protected` or a `public` method. -* `public` methods can be overriden by a `public` method. +* `protected` methods can be overidden by either a `protected` or a `pub` method. +* `pub` methods can be overriden by a `pub` method. Note that method overriding only applies to instance methods. `static` methods are not treated as part of the inheritence hierarcy. @@ -1131,7 +1131,7 @@ The following features are not yet implemented, but we are planning to add them ### 1.14 Roadmap -* Module type visibility (exports/`public` types) is not implemented yet - see https://github.com/winglang/wing/issues/130 to track. +* Module type visibility (exports/`pub` types) is not implemented yet - see https://github.com/winglang/wing/issues/130 to track. * `internal` access modifier is not yet implemented - see https://github.com/winglang/wing/issues/4156 to track. ## 2. Statements @@ -1376,7 +1376,7 @@ class Bar { this.z = new Foo(); this.log(); // OK to call here } - public log() { + pub log() { log("${this.y}"); } } @@ -1397,7 +1397,7 @@ their "strict" mode. class Foo { x: num; init() { this.x = 0; } - public method() { } + pub method() { } } class Boo extends Foo { init() { @@ -1415,7 +1415,7 @@ Classes can implement interfaces iff the interfaces do not contain `inflight`. class Foo { x: num; init() { this.x = 0; } - public method() { } + pub method() { } } class Boo extends Foo { init() { super(); this.x = 10; } diff --git a/docs/docs/07-examples/08-classes.md b/docs/docs/07-examples/08-classes.md index e77346f4009..cb78702f43d 100644 --- a/docs/docs/07-examples/08-classes.md +++ b/docs/docs/07-examples/08-classes.md @@ -28,7 +28,7 @@ class Foo { log("at inflight init"); } - public inflight doStuff() { + pub inflight doStuff() { // all code is async and runs on the cloud log("field3[0]='${this.field3.at(0)}'"); util.sleep(1s); @@ -55,7 +55,7 @@ interface IProfile { } inflight class WingPerson impl IProfile { - public inflight name(): str { + pub inflight name(): str { return "Fairy Wing"; } } @@ -84,10 +84,10 @@ class BucketBasedKeyValueStore impl IKVStore { init() { this.bucket = new cloud.Bucket(); } - public inflight get(key: str): Json { + pub inflight get(key: str): Json { return this.bucket.getJson(key); } - public inflight set(key: str, value: Json): void { + pub inflight set(key: str, value: Json): void { this.bucket.putJson(key, value); } } @@ -108,10 +108,10 @@ class BucketBasedKeyValueStore impl IKVStore { init() { this.bucket = new cloud.Bucket(); } - public inflight get(key: str): Json { + pub inflight get(key: str): Json { return this.bucket.getJson(key); } - public inflight set(key: str, value: Json): void { + pub inflight set(key: str, value: Json): void { this.bucket.putJson(key, value); } } @@ -127,10 +127,10 @@ class TableBasedKeyValueStore impl IKVStore { } ); } - public inflight get(key: str): Json { + pub inflight get(key: str): Json { return this.table.get(key); } - public inflight set(key: str, value: Json): str { + pub inflight set(key: str, value: Json): str { this.table.insert(key, value); } } diff --git a/examples/proposed/cacheable-function.w b/examples/proposed/cacheable-function.w index 0fdb66ca309..40312c7118d 100644 --- a/examples/proposed/cacheable-function.w +++ b/examples/proposed/cacheable-function.w @@ -9,7 +9,7 @@ resource CachableFunction extends cloud.Function { this._cache = new cloud.Bucket(); } - public override inflight invoke(event: any): any { + pub override inflight invoke(event: any): any { let key = hashof(event); let cached = this._cache.try_get(key); if cached { diff --git a/examples/proposed/counting-semaphore.w b/examples/proposed/counting-semaphore.w index b73f2e18da7..babbab1dda6 100644 --- a/examples/proposed/counting-semaphore.w +++ b/examples/proposed/counting-semaphore.w @@ -5,7 +5,7 @@ struct CountingSemaphoreProps { } resource CountingSemaphore { - public limit: num; + pub limit: num; _counter: cloud.Counter; // need some ttl solution here, @@ -19,7 +19,7 @@ resource CountingSemaphore { // some stable unique instance id is wanted in the inflight context // so that a resource instance can be properly claimed and later released // when used in conjunction with a key-value store - public inflight try_acquire(): bool { + pub inflight try_acquire(): bool { if this.is_at_capacity() { return false; } @@ -35,7 +35,7 @@ resource CountingSemaphore { // probably key-value store is wanted, // so that a specific resource instance can be released // rather than naively releasing a count - public inflight release() { + pub inflight release() { if this._counter.peek() <= 0 { return; } @@ -43,7 +43,7 @@ resource CountingSemaphore { this._counter.dec(); } - public inflight is_at_capacity(): bool { + pub inflight is_at_capacity(): bool { return this._counter.peek() >= this.limit; } } diff --git a/examples/tests/invalid/access_modifiers.main.w b/examples/tests/invalid/access_modifiers.main.w index 025eb7d1c62..cf0cc12b912 100644 --- a/examples/tests/invalid/access_modifiers.main.w +++ b/examples/tests/invalid/access_modifiers.main.w @@ -7,7 +7,7 @@ interface SomeInterface { class Foo impl SomeInterface { protected protected_field: str; private_field: str; - public public_field: str; + pub public_field: str; init() { this.protected_field = "hello"; @@ -34,13 +34,13 @@ class Foo impl SomeInterface { } } - public public_method() {} + pub public_method() {} protected protected_method() {} // ^ Method is not public but it's part of an interface private_method() {} //^ Method is not public but it's part of an interface - public static public_static_method() {} + pub static public_static_method() {} protected static protected_static_method() {} static private_static_method() {} } @@ -162,8 +162,8 @@ class FooOverrideToProtected extends Foo { } class FooOverrideToPublic extends Foo { - public public_method() {} - public protected_method() {} - public private_method() {} + pub public_method() {} + pub protected_method() {} + pub private_method() {} // ^ Cannot override } diff --git a/examples/tests/invalid/access_static_from_instance.main.w b/examples/tests/invalid/access_static_from_instance.main.w index 82916dc4b4d..708a248b5b3 100644 --- a/examples/tests/invalid/access_static_from_instance.main.w +++ b/examples/tests/invalid/access_static_from_instance.main.w @@ -1,9 +1,9 @@ class Foo { instanceField: num; - public static f: num; + pub static f: num; - public static m() { + pub static m() { this.instanceField = 1; // Can't access instance fields from static methods this.f = 1; // Can't access static fields through `this` } diff --git a/examples/tests/invalid/call_inflight_from_preflight.main.w b/examples/tests/invalid/call_inflight_from_preflight.main.w index f42b8c14227..7c18edd1007 100644 --- a/examples/tests/invalid/call_inflight_from_preflight.main.w +++ b/examples/tests/invalid/call_inflight_from_preflight.main.w @@ -5,7 +5,7 @@ util.sleep(1s); //^^^^^^^^^^^^^^ Cannot call into inflight phase while preflight class Foo { - public inflight do() {} + pub inflight do() {} } let foo = new Foo(); // Call an inflight method diff --git a/examples/tests/invalid/impl_interface.main.w b/examples/tests/invalid/impl_interface.main.w index e5100ed76b1..0587c593145 100644 --- a/examples/tests/invalid/impl_interface.main.w +++ b/examples/tests/invalid/impl_interface.main.w @@ -5,7 +5,7 @@ class A impl cloud.IQueueSetConsumerHandler { } class B impl cloud.IQueueSetConsumerHandler { - public inflight handle(x: num) { + pub inflight handle(x: num) { // Error: Expected type to be "inflight (str): void", but got "inflight (num): void" instead return; } diff --git a/examples/tests/invalid/inflight_class_interface_structural_typing.main.w b/examples/tests/invalid/inflight_class_interface_structural_typing.main.w index 9f35f92ad0c..d5c3d5dba9d 100644 --- a/examples/tests/invalid/inflight_class_interface_structural_typing.main.w +++ b/examples/tests/invalid/inflight_class_interface_structural_typing.main.w @@ -13,7 +13,7 @@ inflight class NotGoo { test "f" { inflight class YesGoo impl IGoo { - public notHandle(): void { + pub notHandle(): void { log("i am goo"); } } diff --git a/examples/tests/invalid/inflight_ref_explicit_ops.main.w b/examples/tests/invalid/inflight_ref_explicit_ops.main.w index 065a55454ac..4ec287fab90 100644 --- a/examples/tests/invalid/inflight_ref_explicit_ops.main.w +++ b/examples/tests/invalid/inflight_ref_explicit_ops.main.w @@ -2,14 +2,14 @@ bring cloud; class Another { myQueue: cloud.Queue; - public anotherStr: str; + pub anotherStr: str; init () { this.myQueue = new cloud.Queue(); this.anotherStr = "bang"; } - public inflight inflightReturnsResource(): cloud.Queue { + pub inflight inflightReturnsResource(): cloud.Queue { return this.myQueue; // ^^^^^^^^ Cannot qualify access to a lifted object } @@ -30,7 +30,7 @@ class Test { this.justStr = "hello"; } - public inflight test1() { + pub inflight test1() { let x = this.b; // ^ Cannot qualify access to a lifted object x.put("hello", "world"); @@ -38,17 +38,17 @@ class Test { this.justBucket.put("hello", "world"); } - public inflight test2() { + pub inflight test2() { let q = this.another.inflightReturnsResource(); q.push("push!"); } - public inflight test3() { + pub inflight test3() { let b = this.array.at(1); assert(b.list().length == 0); } - public inflight test4() { + pub inflight test4() { assert(this.another.anotherStr == "bang"); } } diff --git a/examples/tests/invalid/inflight_ref_resource_sub_method.main.w b/examples/tests/invalid/inflight_ref_resource_sub_method.main.w index 923c0096b50..b2dd9a15825 100644 --- a/examples/tests/invalid/inflight_ref_resource_sub_method.main.w +++ b/examples/tests/invalid/inflight_ref_resource_sub_method.main.w @@ -9,12 +9,12 @@ class Another { this.myQueue = new cloud.Queue(); } - public inflight inflightReturnsResource(): cloud.Queue { + pub inflight inflightReturnsResource(): cloud.Queue { return this.myQueue; // ^^^^^^^^ Cannot qualify access to a lifted object } - public inflight inflightReturnsResource2(): cloud.Queue { + pub inflight inflightReturnsResource2(): cloud.Queue { return globalQueue; // ^^^^^^^^^^^^ Cannot qualify access to a lifted object } @@ -27,7 +27,7 @@ class Test { this.another = new Another(); } - public inflight test() { + pub inflight test() { let q = this.another.inflightReturnsResource(); q.push("push!"); diff --git a/examples/tests/invalid/inflight_ref_unknown_op.main.w b/examples/tests/invalid/inflight_ref_unknown_op.main.w index c09371ebbe6..a0a89280dfc 100644 --- a/examples/tests/invalid/inflight_ref_unknown_op.main.w +++ b/examples/tests/invalid/inflight_ref_unknown_op.main.w @@ -9,7 +9,7 @@ class Test { this.b = new cloud.Bucket(); } - public inflight test() { + pub inflight test() { let x = this.b; // ^ Cannot qualify which operations are performed on object x.put("hello", "world"); diff --git a/examples/tests/invalid/nil.main.w b/examples/tests/invalid/nil.main.w index c292a762a52..1f702841714 100644 --- a/examples/tests/invalid/nil.main.w +++ b/examples/tests/invalid/nil.main.w @@ -9,7 +9,7 @@ class Foo { this.bar = 1; } - public inflight setBar(b: num) { + pub inflight setBar(b: num) { this.bar = b; } } diff --git a/examples/tests/invalid/preflight_from_inflight.main.w b/examples/tests/invalid/preflight_from_inflight.main.w index cdd60a2c6c1..1602b84d2de 100644 --- a/examples/tests/invalid/preflight_from_inflight.main.w +++ b/examples/tests/invalid/preflight_from_inflight.main.w @@ -1,7 +1,7 @@ bring cloud; class MyResource { - public myPreflight() { } + pub myPreflight() { } } class Test { diff --git a/examples/tests/invalid/reassign_to_nonreassignable.main.w b/examples/tests/invalid/reassign_to_nonreassignable.main.w index 70f291092dd..64a8c75278a 100644 --- a/examples/tests/invalid/reassign_to_nonreassignable.main.w +++ b/examples/tests/invalid/reassign_to_nonreassignable.main.w @@ -3,7 +3,7 @@ let x = 5; x = x + 1; class InnerR { - public inflight inner: num; + pub inflight inner: num; inflight init() { this.inner = 1; } diff --git a/examples/tests/invalid/resource_access_field_as_method.main.w b/examples/tests/invalid/resource_access_field_as_method.main.w index b56be62be9c..1d3b2d5f405 100644 --- a/examples/tests/invalid/resource_access_field_as_method.main.w +++ b/examples/tests/invalid/resource_access_field_as_method.main.w @@ -1,5 +1,5 @@ class SomeResource { - public name: str; + pub name: str; init() { this.name = "John Doe"; } diff --git a/examples/tests/sdk_tests/function/logging.main.w b/examples/tests/sdk_tests/function/logging.main.w index dc77a7bec0e..b33d0190cdf 100644 --- a/examples/tests/sdk_tests/function/logging.main.w +++ b/examples/tests/sdk_tests/function/logging.main.w @@ -1,7 +1,7 @@ bring cloud; class Util { - extern "./logging.js" public static inflight logging(): void; + extern "./logging.js" pub static inflight logging(): void; } let f1 = new cloud.Function(inflight (input: str): void => { diff --git a/examples/tests/sdk_tests/queue/set_consumer.main.w b/examples/tests/sdk_tests/queue/set_consumer.main.w index 51a52e1fdce..fb863d004f2 100644 --- a/examples/tests/sdk_tests/queue/set_consumer.main.w +++ b/examples/tests/sdk_tests/queue/set_consumer.main.w @@ -12,7 +12,7 @@ class Predicate { this.c = c; } - public inflight test(): bool{ + pub inflight test(): bool{ return this.c.peek() == 2; } } diff --git a/examples/tests/sdk_tests/topic/on_message.main.w b/examples/tests/sdk_tests/topic/on_message.main.w index a83f9b39c8c..126da265559 100644 --- a/examples/tests/sdk_tests/topic/on_message.main.w +++ b/examples/tests/sdk_tests/topic/on_message.main.w @@ -10,7 +10,7 @@ class Predicate { this.c = c; } - public inflight test(): bool{ + pub inflight test(): bool{ return this.c.peek() == 10; } } diff --git a/examples/tests/sdk_tests/util/sleep.main.w b/examples/tests/sdk_tests/util/sleep.main.w index b67f01fb60c..5793ac20349 100644 --- a/examples/tests/sdk_tests/util/sleep.main.w +++ b/examples/tests/sdk_tests/util/sleep.main.w @@ -1,7 +1,7 @@ bring util; class JSHelper { - extern "./sleep-helper.js" public static inflight getTime(): num; + extern "./sleep-helper.js" pub static inflight getTime(): num; } let oneHundredMiliseconds = 0.1s; diff --git a/examples/tests/sdk_tests/util/uuidv4.main.w b/examples/tests/sdk_tests/util/uuidv4.main.w index b03bef30aba..da958280ad6 100644 --- a/examples/tests/sdk_tests/util/uuidv4.main.w +++ b/examples/tests/sdk_tests/util/uuidv4.main.w @@ -1,14 +1,14 @@ bring util; class JSHelper { - extern "./uuidv4-helper.js" public static validateUUIDv4(uuidv4: str): bool; + extern "./uuidv4-helper.js" pub static validateUUIDv4(uuidv4: str): bool; } let data = util.uuidv4(); assert(JSHelper.validateUUIDv4(data) == true); class JSHelperInflight { - extern "./uuidv4-helper.js" public static inflight validateUUIDv4(uuidv4: str): bool; + extern "./uuidv4-helper.js" pub static inflight validateUUIDv4(uuidv4: str): bool; } test "inflight uuidv4" { diff --git a/examples/tests/sdk_tests/util/wait-until.main.w b/examples/tests/sdk_tests/util/wait-until.main.w index 2c67715adb4..44e454d451c 100644 --- a/examples/tests/sdk_tests/util/wait-until.main.w +++ b/examples/tests/sdk_tests/util/wait-until.main.w @@ -2,7 +2,7 @@ bring cloud; bring util; class JSHelper { - extern "./sleep-helper.js" public static inflight getTime(): num; + extern "./sleep-helper.js" pub static inflight getTime(): num; } let invokeCounter = new cloud.Counter(); diff --git a/examples/tests/sdk_tests/website/website.main.w b/examples/tests/sdk_tests/website/website.main.w index 3cff75740ff..88c1f0ee0a2 100644 --- a/examples/tests/sdk_tests/website/website.main.w +++ b/examples/tests/sdk_tests/website/website.main.w @@ -5,7 +5,7 @@ let w = new cloud.Website(path: "./website"); let config = Json { json: 1 }; class Util { - extern "../external/fs.js" public static readFile(path: str): str; + extern "../external/fs.js" pub static readFile(path: str): str; } let indexFile = Util.readFile("./website/website/index.html"); diff --git a/examples/tests/valid/assertions.w b/examples/tests/valid/assertions.w index bdaae595461..a62a5bf74a1 100644 --- a/examples/tests/valid/assertions.w +++ b/examples/tests/valid/assertions.w @@ -1,5 +1,5 @@ inflight class Assert { - public static equalStr(a: str, b: str): bool { + pub static equalStr(a: str, b: str): bool { try { assert(a == b); } catch e { @@ -7,7 +7,7 @@ inflight class Assert { } } - public static isNil(a: str?): bool { + pub static isNil(a: str?): bool { try { assert(a == nil); } catch e { @@ -16,7 +16,7 @@ inflight class Assert { } } - public static equalNum(a: num, b: num): bool{ + pub static equalNum(a: num, b: num): bool{ try { assert(a == b); } catch e { diff --git a/examples/tests/valid/baz.w b/examples/tests/valid/baz.w index 1d250d59ac9..6ede63e6be9 100644 --- a/examples/tests/valid/baz.w +++ b/examples/tests/valid/baz.w @@ -1,7 +1,7 @@ // used by bring_local_normalization.w class Baz { - public static baz(): str { + pub static baz(): str { return "baz"; } } diff --git a/examples/tests/valid/bring_local.main.w b/examples/tests/valid/bring_local.main.w index 03a12ad0074..1af2ed68182 100644 --- a/examples/tests/valid/bring_local.main.w +++ b/examples/tests/valid/bring_local.main.w @@ -23,7 +23,7 @@ assert(c != file1.Color.RED); // interfaces from other files can be used class Triangle impl file1.Shape { - public area(): num { + pub area(): num { return 1; } } diff --git a/examples/tests/valid/call_static_of_myself.main.w b/examples/tests/valid/call_static_of_myself.main.w index a38c2b03bd5..e82bc2bd72e 100644 --- a/examples/tests/valid/call_static_of_myself.main.w +++ b/examples/tests/valid/call_static_of_myself.main.w @@ -1,17 +1,17 @@ class Foo { - public static inflight foo(): num { return 1; } + pub static inflight foo(): num { return 1; } static inflight bar(): num { return Foo.foo(); } - public inflight callThis(): num { + pub inflight callThis(): num { return Foo.bar(); } } inflight class Bar { - public static bar(): num { return 2; } + pub static bar(): num { return 2; } - public callThis(): num { + pub callThis(): num { return Bar.bar(); } } @@ -20,7 +20,7 @@ let foo = new Foo(); test "test" { class Zoo { - public static zoo(): num { return 3; } + pub static zoo(): num { return 3; } } let bar = new Bar(); diff --git a/examples/tests/valid/calling_inflight_variants.main.w b/examples/tests/valid/calling_inflight_variants.main.w index 30c601cebda..feb6fea9614 100644 --- a/examples/tests/valid/calling_inflight_variants.main.w +++ b/examples/tests/valid/calling_inflight_variants.main.w @@ -27,14 +27,14 @@ class Foo { } } - public inflight callFn(x: bool): num { + pub inflight callFn(x: bool): num { // partialFn could be an inflight function created during preflight or inflight, // so we have to code-generate this to work for both cases let partialFn = this.makeFn(x); return partialFn(); } - public inflight callFn2(): void { + pub inflight callFn2(): void { // now we call inflight1 and inflight2 directly which know they are handler classes let one = this.inflight1(); let two = this.inflight2(); diff --git a/examples/tests/valid/capture_reassigable_class_field.main.w b/examples/tests/valid/capture_reassigable_class_field.main.w index 31f793ca835..b3aaa6a26d3 100644 --- a/examples/tests/valid/capture_reassigable_class_field.main.w +++ b/examples/tests/valid/capture_reassigable_class_field.main.w @@ -9,15 +9,15 @@ class KeyValueStore { this.onUpdateCallback = inflight (k: str) => {}; } - public onUpdate(fn: inflight (str):void){ + pub onUpdate(fn: inflight (str):void){ this.onUpdateCallback = fn; } - public inflight get(key: str): Json { + pub inflight get(key: str): Json { this.onUpdateCallback(key); return this.bucket.getJson(key); } - public inflight set(key: str, value: Json): void { + pub inflight set(key: str, value: Json): void { this.bucket.putJson(key, value); } } diff --git a/examples/tests/valid/capture_resource_with_no_inflight.main.w b/examples/tests/valid/capture_resource_with_no_inflight.main.w index 3fdac921141..23881c55ffc 100644 --- a/examples/tests/valid/capture_resource_with_no_inflight.main.w +++ b/examples/tests/valid/capture_resource_with_no_inflight.main.w @@ -1,7 +1,7 @@ bring cloud; class A { - public field: str; + pub field: str; counter: cloud.Counter; init() { @@ -13,7 +13,7 @@ class A { this.counter.inc(); } - public inflight bar() { } + pub inflight bar() { } } let a = new A(); diff --git a/examples/tests/valid/capture_tokens.main.w b/examples/tests/valid/capture_tokens.main.w index f5bdc26db5f..de64a6c9b5a 100644 --- a/examples/tests/valid/capture_tokens.main.w +++ b/examples/tests/valid/capture_tokens.main.w @@ -4,14 +4,14 @@ class MyResource { api: cloud.Api; url: str; - extern "./url_utils.js" public static inflight isValidUrl(url: str): bool; + extern "./url_utils.js" pub static inflight isValidUrl(url: str): bool; init() { this.api = new cloud.Api(); this.url = this.api.url; } - public inflight foo() { + pub inflight foo() { assert(MyResource.isValidUrl(this.url)); assert(MyResource.isValidUrl(this.api.url)); } diff --git a/examples/tests/valid/class.main.w b/examples/tests/valid/class.main.w index b8c246d90c9..3f6b21431d5 100644 --- a/examples/tests/valid/class.main.w +++ b/examples/tests/valid/class.main.w @@ -6,7 +6,7 @@ new C1(); // class with init and no arguments class C2 { - public x: num; + pub x: num; init() { this.x = 1; } @@ -16,8 +16,8 @@ assert(c2.x == 1); // class with init and arguments class C3 { - public x: num; - public y: num; + pub x: num; + pub y: num; init(a: num, b: num) { this.x = a; if true { @@ -31,19 +31,19 @@ assert(c3.y == 2); // class with static method and no init class C4 { - public static m():num {return 1;} + pub static m():num {return 1;} } assert(C4.m() == 1); // class with inflight field class C5 { - public inflight x: num; - public inflight var y: num; + pub inflight x: num; + pub inflight var y: num; inflight init() { this.x = 123; this.y = 321; } - public inflight set(b: num) { + pub inflight set(b: num) { this.y = b; } } @@ -57,14 +57,14 @@ test "access inflight field" { } class Person { - public name: str; + pub name: str; init(name: str) { this.name = name; } } class Student extends Person { - public major: str; + pub major: str; init(name: str, major: str) { super(name); @@ -73,7 +73,7 @@ class Student extends Person { } class PaidStudent extends Student { - public hrlyWage: num; + pub hrlyWage: num; init(name: str, major: str, hrlyWage: num) { super(name, major); this.hrlyWage = hrlyWage; @@ -103,7 +103,7 @@ test "devived class init body happens after super" { // Inflight inheritence inflight class A { - public sound: str; + pub sound: str; inflight init(sound: str) { this.sound = sound; diff --git a/examples/tests/valid/closure_class.main.w b/examples/tests/valid/closure_class.main.w index 373fb2f326c..343d5268fd6 100644 --- a/examples/tests/valid/closure_class.main.w +++ b/examples/tests/valid/closure_class.main.w @@ -1,5 +1,5 @@ class MyClosure { - public inflight another(): str { + pub inflight another(): str { return "hello"; } diff --git a/examples/tests/valid/double_reference.main.w b/examples/tests/valid/double_reference.main.w index 4a943d5b94d..069c9898a39 100644 --- a/examples/tests/valid/double_reference.main.w +++ b/examples/tests/valid/double_reference.main.w @@ -7,16 +7,16 @@ class Foo { initCount.inc(); } - public inflight method() { } + pub inflight method() { } } class Bar { - public foo: Foo; + pub foo: Foo; init() { this.foo = new Foo(); } - public inflight callFoo() { + pub inflight callFoo() { this.foo.method(); } } diff --git a/examples/tests/valid/doubler.main.w b/examples/tests/valid/doubler.main.w index 231e95bc9b1..ae7b6c1330c 100644 --- a/examples/tests/valid/doubler.main.w +++ b/examples/tests/valid/doubler.main.w @@ -23,7 +23,7 @@ let fn = new Doubler(inflight (m: str): str => { class Doubler2 { // TODO: make into a static method - see https://github.com/winglang/wing/issues/2583 - public makeFunc(handler: inflight (num): num): cloud.Function { + pub makeFunc(handler: inflight (num): num): cloud.Function { return new cloud.Function(inflight (x: str): str => { let xStr = num.fromStr(x); let y = handler(xStr); diff --git a/examples/tests/valid/dynamo.main.w b/examples/tests/valid/dynamo.main.w index b73a6b98e23..62e4b2d8e4b 100644 --- a/examples/tests/valid/dynamo.main.w +++ b/examples/tests/valid/dynamo.main.w @@ -42,7 +42,7 @@ class DynamoTable { this.tableName = this.table.name; } - public bind(host: std.IInflightHost, ops: Array) { + pub bind(host: std.IInflightHost, ops: Array) { if let host = aws.Function.from(host) { if ops.contains("putItem") { host.addPolicyStatements([aws.PolicyStatement { @@ -56,7 +56,7 @@ class DynamoTable { extern "./dynamo.js" static inflight _putItem(tableName: str, item: Json): void; - public inflight putItem(item: Map) { + pub inflight putItem(item: Map) { let json = this._itemToJson(item); DynamoTable._putItem(this.tableName, json); } diff --git a/examples/tests/valid/dynamo_awscdk.main.w b/examples/tests/valid/dynamo_awscdk.main.w index 95abc3de0e9..5be0801c0e9 100644 --- a/examples/tests/valid/dynamo_awscdk.main.w +++ b/examples/tests/valid/dynamo_awscdk.main.w @@ -40,7 +40,7 @@ class DynamoTable { this.tableName = this.table.tableName; } - public bind(host: std.IInflightHost, ops: Array) { + pub bind(host: std.IInflightHost, ops: Array) { if let host = aws.Function.from(host) { if ops.contains("putItem") { host.addPolicyStatements([aws.PolicyStatement { @@ -61,13 +61,13 @@ class DynamoTable { } extern "./dynamo.js" static inflight _putItem(tableName: str, item: Json): void; - public inflight putItem(item: Map) { + pub inflight putItem(item: Map) { let json = this._itemToJson(item); DynamoTable._putItem(this.tableName, json); } extern "./dynamo.js" static inflight _getItem(tableName: str, key: Json): Json; - public inflight getItem(key: Map): Json { + pub inflight getItem(key: Map): Json { let json = this._itemToJson(key); return DynamoTable._getItem(this.tableName, json); } diff --git a/examples/tests/valid/extern_implementation.main.w b/examples/tests/valid/extern_implementation.main.w index c51019446d2..c4da26f6e79 100644 --- a/examples/tests/valid/extern_implementation.main.w +++ b/examples/tests/valid/extern_implementation.main.w @@ -1,14 +1,14 @@ bring cloud; class Foo { - extern "./external_js.js" public static getGreeting(name: str): str; + extern "./external_js.js" pub static getGreeting(name: str): str; extern "./external_js.js" static inflight regexInflight(pattern: str, text: str): bool; extern "./external_js.js" static inflight getUuid(): str; extern "./external_js.js" static inflight getData(): str; - extern "./external_js.js" public static inflight print(msg: str); - extern "uuid" public static v4(): str; + extern "./external_js.js" pub static inflight print(msg: str); + extern "uuid" pub static v4(): str; - public inflight call() { + pub inflight call() { assert(Foo.regexInflight("[a-z]+-\\d+", "abc-123")); let uuid = Foo.getUuid(); assert(uuid.length == 36); diff --git a/examples/tests/valid/impl_interface.main.w b/examples/tests/valid/impl_interface.main.w index 7e19198894e..7e0db7a9320 100644 --- a/examples/tests/valid/impl_interface.main.w +++ b/examples/tests/valid/impl_interface.main.w @@ -1,7 +1,7 @@ bring cloud; class A impl cloud.IQueueSetConsumerHandler { - public inflight handle(msg: str) { + pub inflight handle(msg: str) { return; } } @@ -25,13 +25,13 @@ interface I3 extends I2 { } class r impl I3 { - public method1(x: num): num { + pub method1(x: num): num { return x; } - public inflight method2(x: str): str { + pub inflight method2(x: str): str { return x; } - public method3(x: Array): Array { + pub method3(x: Array): Array { return x; } } @@ -42,7 +42,7 @@ interface IAnimal { } class Dog impl IAnimal { - public inflight eat() { + pub inflight eat() { return; } } @@ -51,7 +51,7 @@ let z: IAnimal = new Dog(); // base class is checked for implemention of interface class Terrier extends Dog { - public inflight eat() { + pub inflight eat() { return; } } diff --git a/examples/tests/valid/inflight_capture_static.main.w b/examples/tests/valid/inflight_capture_static.main.w index 8220f9a7856..ffc45595046 100644 --- a/examples/tests/valid/inflight_capture_static.main.w +++ b/examples/tests/valid/inflight_capture_static.main.w @@ -1,13 +1,13 @@ bring util; class Preflight { - public static inflight staticMethod(a: num): str { + pub static inflight staticMethod(a: num): str { return "foo-${a}"; } } inflight class OuterInflight { - public static staticMethod(b: str): num { + pub static staticMethod(b: str): num { return b.length; } } @@ -22,7 +22,7 @@ test "call static method of an outer inflight class" { test "call static method of an inner inflight class" { class InnerInflight { - public static staticMethod(): str { return "hello"; } + pub static staticMethod(): str { return "hello"; } } assert(InnerInflight.staticMethod() == "hello"); diff --git a/examples/tests/valid/inflight_class_as_struct_members.main.w b/examples/tests/valid/inflight_class_as_struct_members.main.w index 0d2f06d67e1..36ddb68735e 100644 --- a/examples/tests/valid/inflight_class_as_struct_members.main.w +++ b/examples/tests/valid/inflight_class_as_struct_members.main.w @@ -1,5 +1,5 @@ inflight class Foo { - public get(): num { return 42; } + pub get(): num { return 42; } } struct Bar { diff --git a/examples/tests/valid/inflight_class_capture_const.main.w b/examples/tests/valid/inflight_class_capture_const.main.w index 3e48bcdcbc9..36226868c35 100644 --- a/examples/tests/valid/inflight_class_capture_const.main.w +++ b/examples/tests/valid/inflight_class_capture_const.main.w @@ -3,7 +3,7 @@ bring cloud; let myConst = "bang bang"; inflight class Foo { - public getValue(): str { + pub getValue(): str { return myConst; } } diff --git a/examples/tests/valid/inflight_class_definitions.main.w b/examples/tests/valid/inflight_class_definitions.main.w index 8cbb986b2b9..aea6633422a 100644 --- a/examples/tests/valid/inflight_class_definitions.main.w +++ b/examples/tests/valid/inflight_class_definitions.main.w @@ -1,18 +1,18 @@ class A { - public foo(): str { return "a1"; } - public inflight goo(): str { return "a2"; } + pub foo(): str { return "a1"; } + pub inflight goo(): str { return "a2"; } } let a = new A(); assert(a.foo() == "a1"); inflight class B { - public foo(): str { return "b1"; } + pub foo(): str { return "b1"; } } let fn = inflight () => { inflight class C { - public foo(): str { return "c1"; } + pub foo(): str { return "c1"; } } let c = new C(); @@ -24,14 +24,14 @@ class D { init() { class E { - public foo(): str { return "e1"; } + pub foo(): str { return "e1"; } } let pb = new E(); assert(pb.foo() == "e1"); inflight class F { - public foo(): str { return "f1"; } + pub foo(): str { return "f1"; } } this.inner = inflight (): str => { @@ -39,11 +39,11 @@ class D { }; } - public getInner(): inflight (): str { + pub getInner(): inflight (): str { return this.inner; } - public inflight callInner(): str { + pub inflight callInner(): str { return this.inner(); } } diff --git a/examples/tests/valid/inflight_class_inner_capture_mutable.main.w b/examples/tests/valid/inflight_class_inner_capture_mutable.main.w index d6106a6d7b9..0ec5ee9acb7 100644 --- a/examples/tests/valid/inflight_class_inner_capture_mutable.main.w +++ b/examples/tests/valid/inflight_class_inner_capture_mutable.main.w @@ -5,7 +5,7 @@ test "inner inflight class capture immutable" { let var i = 10; class Inner { - public dang(): num { + pub dang(): num { y.push(2); // since the inner class is defined within the same scope, it is actually possible to reassign diff --git a/examples/tests/valid/inflight_class_inside_inflight_closure.main.w b/examples/tests/valid/inflight_class_inside_inflight_closure.main.w index 8242d1b92e0..af7f6f23c03 100644 --- a/examples/tests/valid/inflight_class_inside_inflight_closure.main.w +++ b/examples/tests/valid/inflight_class_inside_inflight_closure.main.w @@ -5,7 +5,7 @@ class PreflightClass { init() { this.b = new cloud.Bucket(); } - public preflight_method(): cloud.Function { + pub preflight_method(): cloud.Function { let inflight_closure = inflight (payload: str) => { this.b.put("k","v"); // Here `this` is the parent class instance inflight class InflightClass { @@ -13,7 +13,7 @@ class PreflightClass { init() { this.field = "value"; } - public inflight method() { + pub inflight method() { assert(this.field == "value"); // Here `this` is the inflight class instance } } @@ -34,7 +34,7 @@ test "it works" { test "inflight class inside closure captures from closure" { let x = 12; class Foo { - public getX(): num { return x; } + pub getX(): num { return x; } } let foo = new Foo(); diff --git a/examples/tests/valid/inflight_class_outside_inflight_closure.main.w b/examples/tests/valid/inflight_class_outside_inflight_closure.main.w index 42904a64f37..8f29146c218 100644 --- a/examples/tests/valid/inflight_class_outside_inflight_closure.main.w +++ b/examples/tests/valid/inflight_class_outside_inflight_closure.main.w @@ -9,7 +9,7 @@ inflight class BinaryOperation { this.rhs = rhs; } - public add(): num { + pub add(): num { return this.lhs + this.rhs; } } diff --git a/examples/tests/valid/inflight_class_structural_interace_handler.main.w b/examples/tests/valid/inflight_class_structural_interace_handler.main.w index d3ccf36a872..e32ea32e6d6 100644 --- a/examples/tests/valid/inflight_class_structural_interace_handler.main.w +++ b/examples/tests/valid/inflight_class_structural_interace_handler.main.w @@ -12,7 +12,7 @@ inflight class NotGoo { test "structure interface types for 'handle'" { inflight class YesGoo impl IGoo { - public handle(): num { + pub handle(): num { return 456; } diff --git a/examples/tests/valid/inflights_calling_inflights.main.w b/examples/tests/valid/inflights_calling_inflights.main.w index 03f8203c94c..d94f331c780 100644 --- a/examples/tests/valid/inflights_calling_inflights.main.w +++ b/examples/tests/valid/inflights_calling_inflights.main.w @@ -29,7 +29,7 @@ class MyResource { }; } - public inflight foo(): str { + pub inflight foo(): str { return this.closure("anything"); } } diff --git a/examples/tests/valid/json.main.w b/examples/tests/valid/json.main.w index 4f9c2a215a0..f67588a3bcd 100644 --- a/examples/tests/valid/json.main.w +++ b/examples/tests/valid/json.main.w @@ -35,7 +35,7 @@ let jj3 = Json getStr(); assert(jj3 == Json "hello"); class Foo { - public SumStr: str; + pub SumStr: str; init() { this.SumStr = "wow!"; } diff --git a/examples/tests/valid/lift_expr_with_this.main.w b/examples/tests/valid/lift_expr_with_this.main.w index 37ca20428ad..4751d2b7564 100644 --- a/examples/tests/valid/lift_expr_with_this.main.w +++ b/examples/tests/valid/lift_expr_with_this.main.w @@ -1,5 +1,5 @@ class Foo { - public value: str; + pub value: str; init() { this.value = "hello"; } } diff --git a/examples/tests/valid/lift_this.main.w b/examples/tests/valid/lift_this.main.w index 2462c9b7f31..e7de134e292 100644 --- a/examples/tests/valid/lift_this.main.w +++ b/examples/tests/valid/lift_this.main.w @@ -6,7 +6,7 @@ class Foo { inflight bar(): num { return this.x; } - public inflight foo(): num { + pub inflight foo(): num { return this.bar() / 2; } } diff --git a/examples/tests/valid/lift_via_closure.main.w b/examples/tests/valid/lift_via_closure.main.w index 9729784bbeb..42233fe7de4 100644 --- a/examples/tests/valid/lift_via_closure.main.w +++ b/examples/tests/valid/lift_via_closure.main.w @@ -7,7 +7,7 @@ let fn = inflight () => { }; class MyClosure { - public bucket: cloud.Bucket; + pub bucket: cloud.Bucket; init() { this.bucket = new cloud.Bucket(); @@ -23,7 +23,7 @@ class MyClosure { this.bucket.put("hello", "world"); } - public inflight listFiles(): Array { + pub inflight listFiles(): Array { bucket2.put("b2", "world"); return this.bucket.list(); } diff --git a/examples/tests/valid/nil.main.w b/examples/tests/valid/nil.main.w index 35d9b8629e5..f7d91d800e0 100644 --- a/examples/tests/valid/nil.main.w +++ b/examples/tests/valid/nil.main.w @@ -7,18 +7,18 @@ class Foo { this.optionalVar = nil; } - public inflight returnNil(t: bool): str? { + pub inflight returnNil(t: bool): str? { if t { return "hello"; } return nil; } - public inflight setOptionalValue(msg: str?) { + pub inflight setOptionalValue(msg: str?) { this.optionalVar = msg; } - public inflight getOptionalValue(): str? { + pub inflight getOptionalValue(): str? { return this.optionalVar; } } diff --git a/examples/tests/valid/optionals.main.w b/examples/tests/valid/optionals.main.w index a655d1762a9..e4ef16812a7 100644 --- a/examples/tests/valid/optionals.main.w +++ b/examples/tests/valid/optionals.main.w @@ -10,7 +10,7 @@ let y: num = x ?? 5; assert(y == 4); class Super { - public name: str; + pub name: str; init() { this.name = "Super"; } } class Sub extends Super { @@ -136,9 +136,9 @@ assert(fun("hello") == "hello"); assert(fun(nil) == "default"); class Node { - public value: num; - public left: Node?; - public right: Node?; + pub value: num; + pub left: Node?; + pub right: Node?; init(value: num, left: Node?, right: Node?) { this.value = value; diff --git a/examples/tests/valid/reassignment.main.w b/examples/tests/valid/reassignment.main.w index c599cb19523..646723c9c45 100644 --- a/examples/tests/valid/reassignment.main.w +++ b/examples/tests/valid/reassignment.main.w @@ -12,7 +12,7 @@ z -= 1; assert(z == 2); class R { - public var f: num; + pub var f: num; f1: num; init() { // Initialize fields in `init` but in an inner scope to make sure @@ -23,7 +23,7 @@ class R { } } - public inc() { + pub inc() { this.f = this.f + 1; } } diff --git a/examples/tests/valid/resource.main.w b/examples/tests/valid/resource.main.w index e0f14643b47..21394369c63 100644 --- a/examples/tests/valid/resource.main.w +++ b/examples/tests/valid/resource.main.w @@ -3,7 +3,7 @@ bring cloud; // User defined resource class Foo { c: cloud.Counter; // Use SDK built in resource in the user defined resource - public inflight inflightField: num; + pub inflight inflightField: num; init() { this.c = new cloud.Counter(); @@ -19,16 +19,16 @@ class Foo { } // Inflight method - public inflight fooInc() { + pub inflight fooInc() { // Call the SDK built in resource's inflight method from our inflight code this.c.inc(); } - public inflight fooGet(): num { + pub inflight fooGet(): num { return this.c.peek(); } - public static inflight fooStatic(): str { + pub static inflight fooStatic(): str { return "foo static"; } } @@ -43,7 +43,7 @@ class Bar { name: str; b: cloud.Bucket; // Use a user defined resource inside another user defined resource - public foo: Foo; + pub foo: Foo; // Use an enum inside a user defined resource to verify enum capturing works e: MyEnum; @@ -58,7 +58,7 @@ class Bar { return "bar static"; } - public inflight myMethod(): str { + pub inflight myMethod(): str { // Call user defined inflight code from another user defined resource this.foo.fooInc(); @@ -69,7 +69,7 @@ class Bar { return this.b.get("foo"); } - public inflight testTypeAccess() { + pub inflight testTypeAccess() { // We purposefully run these test in an inner scope to validate the compiler analyzes the code // correctly and finds type access in inner scopes. if true { @@ -124,13 +124,13 @@ class BigPublisher { }); } - public inflight publish(s: str) { + pub inflight publish(s: str) { this.t.publish(s); this.q.push(s); this.b2.put("foo", s); } - public inflight getObjectCount(): num { + pub inflight getObjectCount(): num { return this.b.list().length; } } diff --git a/examples/tests/valid/resource_as_inflight_literal.main.w b/examples/tests/valid/resource_as_inflight_literal.main.w index 905f3d44222..6c422e17b2e 100644 --- a/examples/tests/valid/resource_as_inflight_literal.main.w +++ b/examples/tests/valid/resource_as_inflight_literal.main.w @@ -1,7 +1,7 @@ bring cloud; class Foo impl cloud.IFunctionHandler { - public inflight handle(message: str): str { + pub inflight handle(message: str): str { return "hello world!"; } } diff --git a/examples/tests/valid/resource_call_static.main.w b/examples/tests/valid/resource_call_static.main.w index dc543183691..23d2adb9bb2 100644 --- a/examples/tests/valid/resource_call_static.main.w +++ b/examples/tests/valid/resource_call_static.main.w @@ -3,7 +3,7 @@ bring cloud; let globalCounter = new cloud.Counter(); class Another { - public static inflight myStaticMethod(): num { + pub static inflight myStaticMethod(): num { return globalCounter.peek(); } } diff --git a/examples/tests/valid/resource_captures.main.w b/examples/tests/valid/resource_captures.main.w index 5e51956b055..98cd744a29e 100644 --- a/examples/tests/valid/resource_captures.main.w +++ b/examples/tests/valid/resource_captures.main.w @@ -1,7 +1,7 @@ bring cloud; class First { - public myResource: cloud.Bucket; + pub myResource: cloud.Bucket; init() { this.myResource = new cloud.Bucket(); @@ -9,19 +9,19 @@ class First { } class Another { - public myField: str; - public first: First; + pub myField: str; + pub first: First; init () { this.myField = "hello!"; this.first = new First(); } - public inflight meaningOfLife(): num { + pub inflight meaningOfLife(): num { return 42; } - public inflight anotherFunc(): str { + pub inflight anotherFunc(): str { return "42"; } } @@ -67,13 +67,13 @@ class MyResource { this.unusedResource = new cloud.Counter(); } - public inflight testNoCapture() { + pub inflight testNoCapture() { let arr = [1,2,3]; assert(arr.length == 3); log("array.len=${arr.length}"); } - public inflight testCaptureCollectionsOfData() { + pub inflight testCaptureCollectionsOfData() { assert(this.arrayOfStr.length == 2); assert(this.arrayOfStr.at(0) == "s1"); assert(this.arrayOfStr.at(1) == "s2"); @@ -84,13 +84,13 @@ class MyResource { assert(!this.setOfStr.has("s3")); } - public inflight testCapturePrimitives() { + pub inflight testCapturePrimitives() { assert(this.myStr == "myString"); assert(this.myNum == 42); assert(this.myBool == true); } - public inflight testCaptureOptional() { + pub inflight testCaptureOptional() { assert(this.myOptStr ?? "" == "myOptString"); } @@ -98,39 +98,39 @@ class MyResource { return this.another; } - public inflight testCaptureResource() { + pub inflight testCaptureResource() { this.myResource.put("f1.txt", "f1"); assert(this.myResource.get("f1.txt") == "f1"); assert(this.myResource.list().length == 1); } - public inflight testNestedInflightField() { + pub inflight testNestedInflightField() { assert(this.another.myField == "hello!"); log("field=${this.another.myField}"); } - public inflight testNestedResource() { + pub inflight testNestedResource() { assert(this.another.first.myResource.list().length == 0); this.another.first.myResource.put("hello", this.myStr); log("this.another.first.myResource:${this.another.first.myResource.get("hello")}"); } // expression within an expression - public inflight testExpressionRecursive() { + pub inflight testExpressionRecursive() { this.myQueue.push(this.myStr); } - public inflight testExternal() { + pub inflight testExternal() { assert(this.extBucket.list().length == 0); assert(this.extNum == 12); } - public inflight testUserDefinedResource() { + pub inflight testUserDefinedResource() { assert(this.another.meaningOfLife() == 42); assert(this.another.anotherFunc() == "42"); } - public inflight testInflightField() { + pub inflight testInflightField() { assert(this.inflightField == 123); } } diff --git a/examples/tests/valid/resource_captures_globals.main.w b/examples/tests/valid/resource_captures_globals.main.w index 56343924089..9a9ea99e3ba 100644 --- a/examples/tests/valid/resource_captures_globals.main.w +++ b/examples/tests/valid/resource_captures_globals.main.w @@ -10,7 +10,7 @@ let globalMapOfNum = Map{ "a" => -5, "b" => 2 }; let globalSetOfStr = Set{ "a", "b" }; class First { - public myResource: cloud.Bucket; + pub myResource: cloud.Bucket; init() { this.myResource = new cloud.Bucket(); @@ -18,8 +18,8 @@ class First { } class Another { - public myField: str; - public first: First; + pub myField: str; + pub first: First; init () { this.myField = "hello!"; @@ -30,12 +30,12 @@ class Another { assert(globalCounter.peek() == 0); } - public inflight myMethod(): num { + pub inflight myMethod(): num { globalCounter.inc(); return globalCounter.peek(); } - public static inflight myStaticMethod(): num { + pub static inflight myStaticMethod(): num { return globalCounter.peek(); } } @@ -51,7 +51,7 @@ class MyResource { let $parentThis = this; class R impl cloud.ITopicOnMessageHandler { - public inflight handle() { + pub inflight handle() { globalCounter.inc(); $parentThis.localCounter.inc(); } @@ -59,7 +59,7 @@ class MyResource { this.localTopic.onMessage(new R()); } - public inflight myPut() { + pub inflight myPut() { this.localTopic.publish("hello"); globalBucket.put("key", "value"); assert(globalStr == "hello"); diff --git a/examples/tests/valid/static_members.main.w b/examples/tests/valid/static_members.main.w index 12a206313a9..f0143b37691 100644 --- a/examples/tests/valid/static_members.main.w +++ b/examples/tests/valid/static_members.main.w @@ -1,13 +1,13 @@ bring cloud; class Foo { - public instanceField: num; + pub instanceField: num; // TODO: Static field initialization not supported yet (https://github.com/winglang/wing/issues/1668) // static staticField: str = "Static resource value"; // static inflight inflightStaticField: str = "Inflight static resource value"; - public static m(): num { return 99; } + pub static m(): num { return 99; } init() { this.instanceField = 100; @@ -27,10 +27,10 @@ assert(Foo.m() == 99); test "test" { inflight class InflightClass { init() {} - public inflight inflightMethod(): str { + pub inflight inflightMethod(): str { return "Inflight method"; } - public static inflight staticInflightMethod(): str { + pub static inflight staticInflightMethod(): str { return "Static inflight method"; } diff --git a/examples/tests/valid/store.w b/examples/tests/valid/store.w index f13058e9a23..78343eefb71 100644 --- a/examples/tests/valid/store.w +++ b/examples/tests/valid/store.w @@ -14,7 +14,7 @@ class Store { this.b.put("data.txt", ""); }); } - public inflight store(data: str) { + pub inflight store(data: str) { this.b.put("data.txt", data); } } diff --git a/examples/tests/valid/subdir/bar.w b/examples/tests/valid/subdir/bar.w index 2a88e40f87d..cb9820be165 100644 --- a/examples/tests/valid/subdir/bar.w +++ b/examples/tests/valid/subdir/bar.w @@ -1,7 +1,7 @@ // used by bring_local_normalization.w class Bar { - public static bar(): str { + pub static bar(): str { return "bar"; } } diff --git a/examples/tests/valid/subdir/foo.w b/examples/tests/valid/subdir/foo.w index 235fae8b12b..3b9f630b1ce 100644 --- a/examples/tests/valid/subdir/foo.w +++ b/examples/tests/valid/subdir/foo.w @@ -4,13 +4,13 @@ bring "./bar.w" as bar; bring "../baz.w" as baz; class Foo { - public static foo(): str { + pub static foo(): str { return "foo"; } - public static bar(): str { + pub static bar(): str { return bar.Bar.bar(); } - public static baz(): str { + pub static baz(): str { return baz.Baz.baz(); } } diff --git a/examples/tests/valid/super_call.main.w b/examples/tests/valid/super_call.main.w index ccda239565f..bcda2042b81 100644 --- a/examples/tests/valid/super_call.main.w +++ b/examples/tests/valid/super_call.main.w @@ -7,13 +7,13 @@ class A { } class B extends A { - public description(): str { + pub description(): str { return "B"; } } class C extends B { - public description(): str { + pub description(): str { return "C extends ${super.description()}"; } } @@ -23,7 +23,7 @@ class D extends C { } class E extends D { - public description(): str { + pub description(): str { return "E extends ${super.description()}"; } } @@ -33,14 +33,14 @@ let e = new E(); assert(e.description() == "E extends C extends B"); inflight class InflightA { - public description(): str { + pub description(): str { return "InflightA"; } } // Test super calls on inflight classes inflight class InflightB extends InflightA { - public description(): str { + pub description(): str { return "InflightB extends ${super.description()}"; } } @@ -54,13 +54,13 @@ test "super call inflight" { bring cloud; let b = new cloud.Bucket(); class BaseClass { - public inflight do(): str { + pub inflight do(): str { return b.get("k"); // BaseClass class required read acceess to b } } class ExtendedClass extends BaseClass { - public inflight do(): str { + pub inflight do(): str { b.put("k", "value"); // This should require write access to b return super.do(); // We expect to add binding permissions based on what `super.do()` requires (read) } diff --git a/libs/tree-sitter-wing/grammar.js b/libs/tree-sitter-wing/grammar.js index 899d2128cd2..04f65e7eeb8 100644 --- a/libs/tree-sitter-wing/grammar.js +++ b/libs/tree-sitter-wing/grammar.js @@ -532,7 +532,7 @@ module.exports = grammar({ async_modifier: ($) => "async", - access_modifier: ($) => choice("public", "protected", "internal"), + access_modifier: ($) => choice("pub", "protected", "internal"), variadic: ($) => "...", diff --git a/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt b/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt index 13f86020f9a..e131747a2df 100644 --- a/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt +++ b/libs/tree-sitter-wing/test/corpus/statements/class_and_resource.txt @@ -74,14 +74,14 @@ class A { inflight init() {} preflight_func() {} async preflight_func() {} - public preflight_func2() {} + pub preflight_func2() {} inflight inflight_func() {} - public inflight inflight_func2(): num {} + pub inflight inflight_func2(): num {} protected inflight inflight_func3(): num {} pf_member: str; internal internal_member: str; inflight if_member: str; - public inflight var if_member2: str; + pub inflight var if_member2: str; protected inflight var if_member3: str; static inflight inflight_field: num; static inflight inflight_method() {} diff --git a/libs/wingc/src/jsify/tests.rs b/libs/wingc/src/jsify/tests.rs index 8bfe0c2f927..42426c70d21 100644 --- a/libs/wingc/src/jsify/tests.rs +++ b/libs/wingc/src/jsify/tests.rs @@ -48,7 +48,7 @@ fn call_static_inflight_from_static_inflight() { assert_compile_ok!( r#" class A { - public static inflight foo() { log("hello"); } + pub static inflight foo() { log("hello"); } } inflight class B { @@ -66,7 +66,7 @@ fn static_local_inflight_class() { r#" test "test" { class A { - public static foo() { log("hello"); } + pub static foo() { log("hello"); } } class B { @@ -86,7 +86,7 @@ fn static_external_inflight_class() { assert_compile_ok!( r#" inflight class A { - public static foo() { log("hello"); } + pub static foo() { log("hello"); } } test "test" { @@ -106,7 +106,7 @@ fn static_external_preflight_class() { assert_compile_ok!( r#" class A { - public static inflight foo() { log("hello"); } + pub static inflight foo() { log("hello"); } } test "test" { @@ -177,8 +177,8 @@ fn preflight_object() { assert_compile_ok!( r#" class A { - public inflight hello() {} - public inflight goodbye() {} + pub inflight hello() {} + pub inflight goodbye() {} } let pf_obj = new A(); test "test" { @@ -247,7 +247,7 @@ fn preflight_nested_object_with_operations() { bring cloud; let b = new cloud.Bucket(); class A { - public bucky: cloud.Bucket; + pub bucky: cloud.Bucket; init() { this.bucky = b; } @@ -269,7 +269,7 @@ fn static_inflight_operation() { let b = new cloud.Bucket(); class A { - public static inflight myop() { + pub static inflight myop() { b.list(); } } @@ -399,7 +399,7 @@ fn capture_type_static_method() { assert_compile_ok!( r#" class Foo { - public static inflight bars(): str { return "bar"; } + pub static inflight bars(): str { return "bar"; } } test "test" { @@ -414,7 +414,7 @@ fn capture_type_static_method_inflight_class() { assert_compile_ok!( r#" inflight class Foo { - public static bar(): str { return "bar"; } + pub static bar(): str { return "bar"; } } test "test" { @@ -545,7 +545,7 @@ fn capture_identifier_from_preflight_scope_with_method_call() { assert_compile_ok!( r#" class Foo { - public inflight bar() {} + pub inflight bar() {} } let f = new Foo(); @@ -563,7 +563,7 @@ fn capture_identifier_from_preflight_scope_with_nested_object() { bring cloud; class Foo { - public b: cloud.Bucket; + pub b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } @@ -692,8 +692,8 @@ fn preflight_value_field() { assert_compile_ok!( r#" class MyType { - public name: str; - public last: str; + pub name: str; + pub last: str; init() { this.name = "hello"; @@ -735,13 +735,13 @@ fn nested_preflight_operation() { r#" bring cloud; class YourType { - public b: cloud.Bucket; + pub b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } } class MyType { - public y: YourType; + pub y: YourType; init() { this.y = new YourType(); } @@ -762,7 +762,7 @@ fn nested_inflight_after_preflight_operation() { r#" bring cloud; class YourType { - public inflight b: str; + pub inflight b: str; inflight init() { this.b = "hello"; } @@ -802,7 +802,7 @@ fn preflight_object_through_property() { bring cloud; class MyType { - public b: cloud.Bucket; + pub b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } @@ -837,7 +837,7 @@ fn reference_static_inflight() { assert_compile_ok!( r#" class MyType { - public static inflight myStaticMethod(): str {} + pub static inflight myStaticMethod(): str {} } test "test" { @@ -858,7 +858,7 @@ fn reference_static_inflight_which_references_preflight_object() { let b = new cloud.Bucket(); class MyType { - public static inflight staticMethod(): str { + pub static inflight staticMethod(): str { b.list(); return "foo"; } @@ -962,7 +962,7 @@ fn transitive_reference() { return this.b.list().length == 0; } - public inflight checkIfEmpty() { + pub inflight checkIfEmpty() { if this.isEmpty() { log("empty!"); } @@ -1012,13 +1012,13 @@ fn transitive_reference_via_static() { let b = new cloud.Bucket(); class MyType { - public static inflight putInBucket() { + pub static inflight putInBucket() { b.put("in", "bucket"); } } class YourType { - public inflight putIndirect() { + pub inflight putIndirect() { MyType.putInBucket(); } } @@ -1053,7 +1053,7 @@ fn transitive_reference_via_inflight_class() { let b = new cloud.Bucket(); inflight class MyInflightClass { - public putInBucket() { + pub putInBucket() { b.put("in", "bucket"); } } @@ -1071,7 +1071,7 @@ fn reference_inflight_class() { assert_compile_ok!( r#" inflight class Foo { - public static a(): str { return "a"; } + pub static a(): str { return "a"; } } test "test" { @@ -1691,7 +1691,7 @@ fn indirect_capture() { b.list(); } - public inflight goo() { + pub inflight goo() { this.foo(); } } @@ -1746,7 +1746,7 @@ fn lift_this() { inflight bar(): num { return this.x; } - public inflight foo(): num { + pub inflight foo(): num { return this.bar() / 2; } } @@ -1859,7 +1859,7 @@ fn closure_field() { }; } - public inflight foo(): str { + pub inflight foo(): str { return this.closure("anything"); } } @@ -1910,7 +1910,7 @@ fn lift_var_with_this() { assert_compile_ok!( r#" class Foo { - public value: str; + pub value: str; init() { this.value = "hello"; } } diff --git a/libs/wingc/src/parser.rs b/libs/wingc/src/parser.rs index 986e78dada7..2b9ccd10592 100644 --- a/libs/wingc/src/parser.rs +++ b/libs/wingc/src/parser.rs @@ -78,7 +78,7 @@ static RESERVED_WORDS: phf::Set<&'static str> = phf_set! { "package", "private", "protected", - "public", + "pub", "internal", "return", "short", @@ -1315,7 +1315,7 @@ impl<'s> Parser<'s> { fn build_access_modifier(&self, am_node: Option) -> DiagnosticResult { match am_node { Some(am_node) => match self.node_text(&am_node) { - "public" => Ok(AccessModifier::Public), + "pub" => Ok(AccessModifier::Public), "protected" => Ok(AccessModifier::Protected), other => self.report_unimplemented_grammar(other, "access modifier", &am_node), }, diff --git a/libs/wingsdk/src/.gen/versions.json b/libs/wingsdk/src/.gen/versions.json index e69de29bb2d..fbe6adcd3fd 100644 --- a/libs/wingsdk/src/.gen/versions.json +++ b/libs/wingsdk/src/.gen/versions.json @@ -0,0 +1,6 @@ +{ + "registry.terraform.io/hashicorp/random": "3.5.1", + "registry.terraform.io/hashicorp/google": "4.63.1", + "registry.terraform.io/hashicorp/azurerm": "3.54.0", + "registry.terraform.io/hashicorp/aws": "4.65.0" +} From 581d66d695ace197731fd2413cc23849b8bf8af0 Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Thu, 14 Sep 2023 14:35:07 +0000 Subject: [PATCH 53/56] chore: self mutation (build.diff) Signed-off-by: monada-bot[bot] --- .../snapshots/call_static_inflight_from_static_inflight.snap | 2 +- ...ture_identifier_from_preflight_scope_with_method_call.snap | 2 +- ...re_identifier_from_preflight_scope_with_nested_object.snap | 2 +- .../wingc/src/jsify/snapshots/capture_type_static_method.snap | 2 +- .../snapshots/capture_type_static_method_inflight_class.snap | 2 +- libs/wingc/src/jsify/snapshots/closure_field.snap | 2 +- libs/wingc/src/jsify/snapshots/indirect_capture.snap | 2 +- libs/wingc/src/jsify/snapshots/lift_this.snap | 2 +- libs/wingc/src/jsify/snapshots/lift_var_with_this.snap | 2 +- .../snapshots/nested_inflight_after_preflight_operation.snap | 2 +- .../wingc/src/jsify/snapshots/nested_preflight_operation.snap | 4 ++-- .../snapshots/preflight_nested_object_with_operations.snap | 2 +- libs/wingc/src/jsify/snapshots/preflight_object.snap | 4 ++-- .../jsify/snapshots/preflight_object_through_property.snap | 2 +- libs/wingc/src/jsify/snapshots/preflight_value_field.snap | 4 ++-- libs/wingc/src/jsify/snapshots/reference_inflight_class.snap | 2 +- libs/wingc/src/jsify/snapshots/reference_static_inflight.snap | 2 +- ...nce_static_inflight_which_references_preflight_object.snap | 2 +- .../src/jsify/snapshots/static_external_inflight_class.snap | 2 +- .../src/jsify/snapshots/static_external_preflight_class.snap | 2 +- libs/wingc/src/jsify/snapshots/static_inflight_operation.snap | 2 +- .../src/jsify/snapshots/static_local_inflight_class.snap | 2 +- libs/wingc/src/jsify/snapshots/transitive_reference.snap | 2 +- .../snapshots/transitive_reference_via_inflight_class.snap | 2 +- .../src/jsify/snapshots/transitive_reference_via_static.snap | 4 ++-- 25 files changed, 29 insertions(+), 29 deletions(-) diff --git a/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap b/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap index 42de6cdd91e..fed5fb60204 100644 --- a/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap +++ b/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class A { - public static inflight foo() { log("hello"); } + pub static inflight foo() { log("hello"); } } inflight class B { diff --git a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap index 1a9e1063b88..712ea37c7bb 100644 --- a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap +++ b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class Foo { - public inflight bar() {} + pub inflight bar() {} } let f = new Foo(); diff --git a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap index 5994f8bd5db..e3231f34797 100644 --- a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap +++ b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class Foo { - public b: cloud.Bucket; + pub b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } diff --git a/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap b/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap index 0f53e74ab48..5380faba38c 100644 --- a/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap +++ b/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class Foo { - public static inflight bars(): str { return "bar"; } + pub static inflight bars(): str { return "bar"; } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap b/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap index 42125948c51..cb71bb818a3 100644 --- a/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w inflight class Foo { - public static bar(): str { return "bar"; } + pub static bar(): str { return "bar"; } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/closure_field.snap b/libs/wingc/src/jsify/snapshots/closure_field.snap index fa3c8b252f8..cac7ba51314 100644 --- a/libs/wingc/src/jsify/snapshots/closure_field.snap +++ b/libs/wingc/src/jsify/snapshots/closure_field.snap @@ -18,7 +18,7 @@ source: libs/wingc/src/jsify/tests.rs }; } - public inflight foo(): str { + pub inflight foo(): str { return this.closure("anything"); } } diff --git a/libs/wingc/src/jsify/snapshots/indirect_capture.snap b/libs/wingc/src/jsify/snapshots/indirect_capture.snap index 7d477edfeac..1b5991e2b14 100644 --- a/libs/wingc/src/jsify/snapshots/indirect_capture.snap +++ b/libs/wingc/src/jsify/snapshots/indirect_capture.snap @@ -16,7 +16,7 @@ source: libs/wingc/src/jsify/tests.rs b.list(); } - public inflight goo() { + pub inflight goo() { this.foo(); } } diff --git a/libs/wingc/src/jsify/snapshots/lift_this.snap b/libs/wingc/src/jsify/snapshots/lift_this.snap index fe65ac5a0a0..7cb3247c887 100644 --- a/libs/wingc/src/jsify/snapshots/lift_this.snap +++ b/libs/wingc/src/jsify/snapshots/lift_this.snap @@ -13,7 +13,7 @@ source: libs/wingc/src/jsify/tests.rs inflight bar(): num { return this.x; } - public inflight foo(): num { + pub inflight foo(): num { return this.bar() / 2; } } diff --git a/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap b/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap index e7edfae2a20..f5ce5b9cb08 100644 --- a/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap +++ b/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class Foo { - public value: str; + pub value: str; init() { this.value = "hello"; } } diff --git a/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap b/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap index 798f0bb5337..cff99aab1a7 100644 --- a/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap +++ b/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap @@ -7,7 +7,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class YourType { - public inflight b: str; + pub inflight b: str; inflight init() { this.b = "hello"; } diff --git a/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap b/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap index 798cbb73b64..246fa7742f5 100644 --- a/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap +++ b/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap @@ -7,13 +7,13 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class YourType { - public b: cloud.Bucket; + pub b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } } class MyType { - public y: YourType; + pub y: YourType; init() { this.y = new YourType(); } diff --git a/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap b/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap index 88478244483..1223a3691cb 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; let b = new cloud.Bucket(); class A { - public bucky: cloud.Bucket; + pub bucky: cloud.Bucket; init() { this.bucky = b; } diff --git a/libs/wingc/src/jsify/snapshots/preflight_object.snap b/libs/wingc/src/jsify/snapshots/preflight_object.snap index 4ae47e7c53e..f77db85d6c7 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_object.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_object.snap @@ -6,8 +6,8 @@ source: libs/wingc/src/jsify/tests.rs ```w class A { - public inflight hello() {} - public inflight goodbye() {} + pub inflight hello() {} + pub inflight goodbye() {} } let pf_obj = new A(); test "test" { diff --git a/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap b/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap index df0bff878e0..a004d3a9079 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class MyType { - public b: cloud.Bucket; + pub b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } diff --git a/libs/wingc/src/jsify/snapshots/preflight_value_field.snap b/libs/wingc/src/jsify/snapshots/preflight_value_field.snap index 9aa911dacd8..2ef2189fcc5 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_value_field.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_value_field.snap @@ -6,8 +6,8 @@ source: libs/wingc/src/jsify/tests.rs ```w class MyType { - public name: str; - public last: str; + pub name: str; + pub last: str; init() { this.name = "hello"; diff --git a/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap b/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap index 704ea18ff21..6c23f30c8e9 100644 --- a/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w inflight class Foo { - public static a(): str { return "a"; } + pub static a(): str { return "a"; } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap b/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap index 802cc769b21..d0fdf926c88 100644 --- a/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap +++ b/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class MyType { - public static inflight myStaticMethod(): str {} + pub static inflight myStaticMethod(): str {} } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap b/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap index 12994c71f20..59da0f9a5a6 100644 --- a/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap +++ b/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap @@ -10,7 +10,7 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); class MyType { - public static inflight staticMethod(): str { + pub static inflight staticMethod(): str { b.list(); return "foo"; } diff --git a/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap b/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap index be03f914efa..ac7a0f7be2b 100644 --- a/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w inflight class A { - public static foo() { log("hello"); } + pub static foo() { log("hello"); } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap b/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap index 4af4b0f4ba3..951b2abea28 100644 --- a/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class A { - public static inflight foo() { log("hello"); } + pub static inflight foo() { log("hello"); } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap b/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap index 6c196395573..613f03e3b9a 100644 --- a/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap +++ b/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap @@ -9,7 +9,7 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); class A { - public static inflight myop() { + pub static inflight myop() { b.list(); } } diff --git a/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap b/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap index fc7702388c6..873a6455a5b 100644 --- a/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap @@ -7,7 +7,7 @@ source: libs/wingc/src/jsify/tests.rs test "test" { class A { - public static foo() { log("hello"); } + pub static foo() { log("hello"); } } class B { diff --git a/libs/wingc/src/jsify/snapshots/transitive_reference.snap b/libs/wingc/src/jsify/snapshots/transitive_reference.snap index e87682f7b45..27cb2f70fb7 100644 --- a/libs/wingc/src/jsify/snapshots/transitive_reference.snap +++ b/libs/wingc/src/jsify/snapshots/transitive_reference.snap @@ -18,7 +18,7 @@ source: libs/wingc/src/jsify/tests.rs return this.b.list().length == 0; } - public inflight checkIfEmpty() { + pub inflight checkIfEmpty() { if this.isEmpty() { log("empty!"); } diff --git a/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap b/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap index e5804c45e79..28689f1c406 100644 --- a/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap @@ -10,7 +10,7 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); inflight class MyInflightClass { - public putInBucket() { + pub putInBucket() { b.put("in", "bucket"); } } diff --git a/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap b/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap index e751a8a0e9e..a9b24f2075e 100644 --- a/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap +++ b/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap @@ -10,13 +10,13 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); class MyType { - public static inflight putInBucket() { + pub static inflight putInBucket() { b.put("in", "bucket"); } } class YourType { - public inflight putIndirect() { + pub inflight putIndirect() { MyType.putInBucket(); } } From fcec0111bcf928781f1ef949b0b8f2a7fcabd0fb Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Thu, 14 Sep 2023 14:35:08 +0000 Subject: [PATCH 54/56] chore: self mutation (e2e-2of2.diff) Signed-off-by: monada-bot[bot] --- tools/hangar/__snapshots__/invalid.ts.snap | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 755c6ff2983..8d15193e76f 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -108,10 +108,10 @@ error: Cannot override private method \\"private_method\\" of \\"Foo\\" error: Cannot override private method \\"private_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.main.w:167:10 + --> ../../../examples/tests/invalid/access_modifiers.main.w:167:7 | -167 | public private_method() {} - | ^^^^^^^^^^^^^^ Cannot override private method \\"private_method\\" of \\"Foo\\" +167 | pub private_method() {} + | ^^^^^^^^^^^^^^ Cannot override private method \\"private_method\\" of \\"Foo\\" error: Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" @@ -216,8 +216,8 @@ exports[`access_static_from_instance.main.w 1`] = ` "error: Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 --> ../../../examples/tests/invalid/access_static_from_instance.main.w:4:3 | -4 | public static f: num; - | ^^^^^^^^^^^^^^^^^^^^^ Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 +4 | pub static f: num; + | ^^^^^^^^^^^^^^^^^^ Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 error: Cannot access static property \\"f\\" from instance From 01c93f1571224b62e18cbecd375998904e382a39 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Thu, 14 Sep 2023 17:45:00 +0300 Subject: [PATCH 55/56] snapshots --- .../call_static_inflight_from_static_inflight.snap | 2 +- ...entifier_from_preflight_scope_with_method_call.snap | 2 +- ...tifier_from_preflight_scope_with_nested_object.snap | 2 +- .../jsify/snapshots/capture_type_static_method.snap | 2 +- .../capture_type_static_method_inflight_class.snap | 2 +- libs/wingc/src/jsify/snapshots/closure_field.snap | 2 +- libs/wingc/src/jsify/snapshots/indirect_capture.snap | 2 +- libs/wingc/src/jsify/snapshots/lift_this.snap | 2 +- libs/wingc/src/jsify/snapshots/lift_var_with_this.snap | 2 +- .../nested_inflight_after_preflight_operation.snap | 2 +- .../jsify/snapshots/nested_preflight_operation.snap | 4 ++-- .../preflight_nested_object_with_operations.snap | 2 +- libs/wingc/src/jsify/snapshots/preflight_object.snap | 4 ++-- .../snapshots/preflight_object_through_property.snap | 2 +- .../src/jsify/snapshots/preflight_value_field.snap | 4 ++-- .../src/jsify/snapshots/reference_inflight_class.snap | 2 +- .../src/jsify/snapshots/reference_static_inflight.snap | 2 +- ...tic_inflight_which_references_preflight_object.snap | 2 +- .../snapshots/static_external_inflight_class.snap | 2 +- .../snapshots/static_external_preflight_class.snap | 2 +- .../src/jsify/snapshots/static_inflight_operation.snap | 2 +- .../jsify/snapshots/static_local_inflight_class.snap | 2 +- .../src/jsify/snapshots/transitive_reference.snap | 2 +- .../transitive_reference_via_inflight_class.snap | 2 +- .../snapshots/transitive_reference_via_static.snap | 4 ++-- tools/hangar/__snapshots__/invalid.ts.snap | 10 +++++----- 26 files changed, 34 insertions(+), 34 deletions(-) diff --git a/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap b/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap index 42de6cdd91e..fed5fb60204 100644 --- a/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap +++ b/libs/wingc/src/jsify/snapshots/call_static_inflight_from_static_inflight.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class A { - public static inflight foo() { log("hello"); } + pub static inflight foo() { log("hello"); } } inflight class B { diff --git a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap index 1a9e1063b88..712ea37c7bb 100644 --- a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap +++ b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_method_call.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class Foo { - public inflight bar() {} + pub inflight bar() {} } let f = new Foo(); diff --git a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap index 5994f8bd5db..e3231f34797 100644 --- a/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap +++ b/libs/wingc/src/jsify/snapshots/capture_identifier_from_preflight_scope_with_nested_object.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class Foo { - public b: cloud.Bucket; + pub b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } diff --git a/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap b/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap index 0f53e74ab48..5380faba38c 100644 --- a/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap +++ b/libs/wingc/src/jsify/snapshots/capture_type_static_method.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class Foo { - public static inflight bars(): str { return "bar"; } + pub static inflight bars(): str { return "bar"; } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap b/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap index 42125948c51..cb71bb818a3 100644 --- a/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/capture_type_static_method_inflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w inflight class Foo { - public static bar(): str { return "bar"; } + pub static bar(): str { return "bar"; } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/closure_field.snap b/libs/wingc/src/jsify/snapshots/closure_field.snap index fa3c8b252f8..cac7ba51314 100644 --- a/libs/wingc/src/jsify/snapshots/closure_field.snap +++ b/libs/wingc/src/jsify/snapshots/closure_field.snap @@ -18,7 +18,7 @@ source: libs/wingc/src/jsify/tests.rs }; } - public inflight foo(): str { + pub inflight foo(): str { return this.closure("anything"); } } diff --git a/libs/wingc/src/jsify/snapshots/indirect_capture.snap b/libs/wingc/src/jsify/snapshots/indirect_capture.snap index 7d477edfeac..1b5991e2b14 100644 --- a/libs/wingc/src/jsify/snapshots/indirect_capture.snap +++ b/libs/wingc/src/jsify/snapshots/indirect_capture.snap @@ -16,7 +16,7 @@ source: libs/wingc/src/jsify/tests.rs b.list(); } - public inflight goo() { + pub inflight goo() { this.foo(); } } diff --git a/libs/wingc/src/jsify/snapshots/lift_this.snap b/libs/wingc/src/jsify/snapshots/lift_this.snap index fe65ac5a0a0..7cb3247c887 100644 --- a/libs/wingc/src/jsify/snapshots/lift_this.snap +++ b/libs/wingc/src/jsify/snapshots/lift_this.snap @@ -13,7 +13,7 @@ source: libs/wingc/src/jsify/tests.rs inflight bar(): num { return this.x; } - public inflight foo(): num { + pub inflight foo(): num { return this.bar() / 2; } } diff --git a/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap b/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap index e7edfae2a20..f5ce5b9cb08 100644 --- a/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap +++ b/libs/wingc/src/jsify/snapshots/lift_var_with_this.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class Foo { - public value: str; + pub value: str; init() { this.value = "hello"; } } diff --git a/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap b/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap index 798f0bb5337..cff99aab1a7 100644 --- a/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap +++ b/libs/wingc/src/jsify/snapshots/nested_inflight_after_preflight_operation.snap @@ -7,7 +7,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class YourType { - public inflight b: str; + pub inflight b: str; inflight init() { this.b = "hello"; } diff --git a/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap b/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap index 798cbb73b64..246fa7742f5 100644 --- a/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap +++ b/libs/wingc/src/jsify/snapshots/nested_preflight_operation.snap @@ -7,13 +7,13 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class YourType { - public b: cloud.Bucket; + pub b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } } class MyType { - public y: YourType; + pub y: YourType; init() { this.y = new YourType(); } diff --git a/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap b/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap index 88478244483..1223a3691cb 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_nested_object_with_operations.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; let b = new cloud.Bucket(); class A { - public bucky: cloud.Bucket; + pub bucky: cloud.Bucket; init() { this.bucky = b; } diff --git a/libs/wingc/src/jsify/snapshots/preflight_object.snap b/libs/wingc/src/jsify/snapshots/preflight_object.snap index 4ae47e7c53e..f77db85d6c7 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_object.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_object.snap @@ -6,8 +6,8 @@ source: libs/wingc/src/jsify/tests.rs ```w class A { - public inflight hello() {} - public inflight goodbye() {} + pub inflight hello() {} + pub inflight goodbye() {} } let pf_obj = new A(); test "test" { diff --git a/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap b/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap index df0bff878e0..a004d3a9079 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_object_through_property.snap @@ -8,7 +8,7 @@ source: libs/wingc/src/jsify/tests.rs bring cloud; class MyType { - public b: cloud.Bucket; + pub b: cloud.Bucket; init() { this.b = new cloud.Bucket(); } diff --git a/libs/wingc/src/jsify/snapshots/preflight_value_field.snap b/libs/wingc/src/jsify/snapshots/preflight_value_field.snap index 9aa911dacd8..2ef2189fcc5 100644 --- a/libs/wingc/src/jsify/snapshots/preflight_value_field.snap +++ b/libs/wingc/src/jsify/snapshots/preflight_value_field.snap @@ -6,8 +6,8 @@ source: libs/wingc/src/jsify/tests.rs ```w class MyType { - public name: str; - public last: str; + pub name: str; + pub last: str; init() { this.name = "hello"; diff --git a/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap b/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap index 704ea18ff21..6c23f30c8e9 100644 --- a/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/reference_inflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w inflight class Foo { - public static a(): str { return "a"; } + pub static a(): str { return "a"; } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap b/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap index 802cc769b21..d0fdf926c88 100644 --- a/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap +++ b/libs/wingc/src/jsify/snapshots/reference_static_inflight.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class MyType { - public static inflight myStaticMethod(): str {} + pub static inflight myStaticMethod(): str {} } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap b/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap index 12994c71f20..59da0f9a5a6 100644 --- a/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap +++ b/libs/wingc/src/jsify/snapshots/reference_static_inflight_which_references_preflight_object.snap @@ -10,7 +10,7 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); class MyType { - public static inflight staticMethod(): str { + pub static inflight staticMethod(): str { b.list(); return "foo"; } diff --git a/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap b/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap index be03f914efa..ac7a0f7be2b 100644 --- a/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/static_external_inflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w inflight class A { - public static foo() { log("hello"); } + pub static foo() { log("hello"); } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap b/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap index 4af4b0f4ba3..951b2abea28 100644 --- a/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/static_external_preflight_class.snap @@ -6,7 +6,7 @@ source: libs/wingc/src/jsify/tests.rs ```w class A { - public static inflight foo() { log("hello"); } + pub static inflight foo() { log("hello"); } } test "test" { diff --git a/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap b/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap index 6c196395573..613f03e3b9a 100644 --- a/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap +++ b/libs/wingc/src/jsify/snapshots/static_inflight_operation.snap @@ -9,7 +9,7 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); class A { - public static inflight myop() { + pub static inflight myop() { b.list(); } } diff --git a/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap b/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap index fc7702388c6..873a6455a5b 100644 --- a/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/static_local_inflight_class.snap @@ -7,7 +7,7 @@ source: libs/wingc/src/jsify/tests.rs test "test" { class A { - public static foo() { log("hello"); } + pub static foo() { log("hello"); } } class B { diff --git a/libs/wingc/src/jsify/snapshots/transitive_reference.snap b/libs/wingc/src/jsify/snapshots/transitive_reference.snap index e87682f7b45..27cb2f70fb7 100644 --- a/libs/wingc/src/jsify/snapshots/transitive_reference.snap +++ b/libs/wingc/src/jsify/snapshots/transitive_reference.snap @@ -18,7 +18,7 @@ source: libs/wingc/src/jsify/tests.rs return this.b.list().length == 0; } - public inflight checkIfEmpty() { + pub inflight checkIfEmpty() { if this.isEmpty() { log("empty!"); } diff --git a/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap b/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap index e5804c45e79..28689f1c406 100644 --- a/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap +++ b/libs/wingc/src/jsify/snapshots/transitive_reference_via_inflight_class.snap @@ -10,7 +10,7 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); inflight class MyInflightClass { - public putInBucket() { + pub putInBucket() { b.put("in", "bucket"); } } diff --git a/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap b/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap index e751a8a0e9e..a9b24f2075e 100644 --- a/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap +++ b/libs/wingc/src/jsify/snapshots/transitive_reference_via_static.snap @@ -10,13 +10,13 @@ source: libs/wingc/src/jsify/tests.rs let b = new cloud.Bucket(); class MyType { - public static inflight putInBucket() { + pub static inflight putInBucket() { b.put("in", "bucket"); } } class YourType { - public inflight putIndirect() { + pub inflight putIndirect() { MyType.putInBucket(); } } diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 755c6ff2983..8d15193e76f 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -108,10 +108,10 @@ error: Cannot override private method \\"private_method\\" of \\"Foo\\" error: Cannot override private method \\"private_method\\" of \\"Foo\\" - --> ../../../examples/tests/invalid/access_modifiers.main.w:167:10 + --> ../../../examples/tests/invalid/access_modifiers.main.w:167:7 | -167 | public private_method() {} - | ^^^^^^^^^^^^^^ Cannot override private method \\"private_method\\" of \\"Foo\\" +167 | pub private_method() {} + | ^^^^^^^^^^^^^^ Cannot override private method \\"private_method\\" of \\"Foo\\" error: Cannot access protected member \\"protected_static_method\\" of \\"Foo\\" @@ -216,8 +216,8 @@ exports[`access_static_from_instance.main.w 1`] = ` "error: Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 --> ../../../examples/tests/invalid/access_static_from_instance.main.w:4:3 | -4 | public static f: num; - | ^^^^^^^^^^^^^^^^^^^^^ Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 +4 | pub static f: num; + | ^^^^^^^^^^^^^^^^^^ Static class fields not supported yet, see https://github.com/winglang/wing/issues/1668 error: Cannot access static property \\"f\\" from instance From 97adb3e291cb4450326e187877ef76a576544b12 Mon Sep 17 00:00:00 2001 From: Yoav Steinberg Date: Fri, 15 Sep 2023 21:00:13 +0300 Subject: [PATCH 56/56] removed ignored/generated file --- libs/wingsdk/src/.gen/versions.json | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 libs/wingsdk/src/.gen/versions.json diff --git a/libs/wingsdk/src/.gen/versions.json b/libs/wingsdk/src/.gen/versions.json deleted file mode 100644 index fbe6adcd3fd..00000000000 --- a/libs/wingsdk/src/.gen/versions.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "registry.terraform.io/hashicorp/random": "3.5.1", - "registry.terraform.io/hashicorp/google": "4.63.1", - "registry.terraform.io/hashicorp/azurerm": "3.54.0", - "registry.terraform.io/hashicorp/aws": "4.65.0" -}