Skip to content
Merged
5 changes: 4 additions & 1 deletion dag/extdeps/languages/dag/syntax.dag
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority {
}

data dag_item_forms: List<ItemForm> = [
ItemForm { kind: OtherForm, keyword: "alias", has_type_params: false, has_params: false,
has_return_type: false, return_required: false,
has_uses: false, body_kind: AliasBody },
ItemForm { kind: TypeAliasForm, keyword: "type", has_type_params: true, has_params: false,
has_return_type: false, return_required: false,
has_uses: false, body_kind: TypeBody },
Expand Down Expand Up @@ -56,7 +59,7 @@ data dag_keyword_literals: Map<String, LiteralValue> = {
}

data dag_keyword_set: Map<String, Bool> = {
"module": true, "import": true, "type": true, "fn": true, "func": true,
"module": true, "import": true, "alias": true, "type": true, "fn": true, "func": true,
"resource": true, "service": true, "data": true,
"interface": true, "pipeline": true, "profile": true, "pattern": true,
"let": true, "return": true, "match": true, "if": true, "then": true, "else": true,
Expand Down
1 change: 1 addition & 0 deletions dag/std/syntax.dag
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type BodyKind
| NoBody
| ServiceBody
| ResourceBody
| AliasBody

type ItemFormKind
= FuncForm
Expand Down
41 changes: 40 additions & 1 deletion src/v1/02_parse.dag
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,7 @@ fn parse_item(tokens: TokenStream, ctx: ParseContext) -> ItemResult {
let form = find_item_form(forms: dag_syntax_spec.item_forms, keyword: kw)
match form {
Present { value: f } => parse_item_by_form(tokens: tokens, ctx: ctx, form: f)
Absent => ItemResult { item: Node { name: "<unknown>", span: span, ident_span: Present { value: span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: "expected item declaration (type, fn, func, service, resource, data, extern, pattern, interface)", span: span) } }
Absent => ItemResult { item: Node { name: "<unknown>", span: span, ident_span: Present { value: span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: "expected item declaration (alias, type, fn, func, service, resource, data, extern, pattern, interface)", span: span) } }
}
}

Expand Down Expand Up @@ -1080,6 +1080,7 @@ fn parse_item_by_form(tokens: TokenStream, ctx: ParseContext, form: ItemForm) ->
ServiceBody => parse_service_after_kw(tokens: tokens, ctx: ctx, start_span: start_span)
ResourceBody => parse_resource_after_kw(tokens: tokens, ctx: ctx, start_span: start_span)
ValueBody => parse_data_after_kw(tokens: tokens, ctx: ctx, start_span: start_span)
AliasBody => parse_alias_after_kw(tokens: tokens, ctx: ctx, start_span: start_span)
NoBody => {
let prefix = parse_item_prefix(tokens: tokens, ctx: ctx, form: form)
if has_err(err: prefix.err) { return ItemResult { item: dummy, tokens: prefix.tokens, ctx: prefix.ctx, err: prefix.err } }
Expand Down Expand Up @@ -2973,6 +2974,44 @@ fn parse_data_def(tokens: TokenStream, ctx: ParseContext) -> ItemResult {
parse_data_after_kw(tokens: r.tokens, ctx: ctx, start_span: start_span)
}

fn parse_alias_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: SourceSpan) -> ItemResult {
let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }

let r = expect_ident(tokens: tokens)
if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } }
let name = r.name
let name_span = r.span
let named_dummy = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }

let r = expect(tokens: r.tokens, expected: ExpectEq)
if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: ctx, err: r.err } }

let r = parse_dotted_ident(tokens: r.tokens)
if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: ctx, err: r.err } }
let target_path = r.name

let target_prop = make_field_init_node(
name: "namespace_alias_target",
value: make_expr_node(
expr_data: ExprLiteral { value: LitStr { value: target_path } },
children: [],
inferred: none,
span: r.span
),
span: start_span,
name_span: no_span()
)

let item = Node {
name: name, span: start_span, ident_span: Present { value: name_span }, children: [],
params: [], inferred: none, return_cardinality: Required, uses: [],
body: none, connective: NoConnective, transport: none,
properties: [target_prop], type_annotation: none,
is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData
}
ItemResult { item: item, tokens: skip_newlines(tokens: r.tokens), ctx: ctx, err: none }
}

fn parse_data_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: SourceSpan) -> ItemResult {
let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }

Expand Down
106 changes: 93 additions & 13 deletions src/v1/04_infer.dag
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import std.coercion { dag_can_cast, is_dag_cast_domain_type }
import v1.std.core {
Node, InternTable,
intern, intern_str, empty_intern_table,
authored_name_at, generic_param_name_at, NewlineIndex, find_child_named, has_child_named, build_newline_index,
authored_name_at, generic_param_name_at, NewlineIndex, find_child_named, find_property_string, has_child_named, build_newline_index,
module_node, module_imports, module_items, import_is_all, import_specific_names_at,
make_param_node, param_node_name_at, param_node_type_expr,
field_node_type_expr, field_node_name_at,
Expand Down Expand Up @@ -484,6 +484,29 @@ fn namespace_root_from_properties(properties: List<Node>, name: String, source_i
}
}

fn namespace_alias_target_path(item: Node, source_indices: Map<String, NewlineIndex>) -> String? {
find_property_string(props: item.properties, prop_name: "namespace_alias_target", source_indices: source_indices)
}

fn is_namespace_alias_item(item: Node, source_indices: Map<String, NewlineIndex>) -> Bool {
match namespace_alias_target_path(item: item, source_indices: source_indices) {
Present { value: _ } => true
Absent => false
}
}

fn namespace_alias_binding_for_target(
item: Node,
target_node: Node,
source_indices: Map<String, NewlineIndex>
) -> TypeBinding {
TypeBinding {
name: authored_name_at(source_indices: source_indices, node: item),
resolved: target_node,
provenance: SubValueUnknown
}
}

fn expr_span(texpr: Node) -> SourceSpan {
texpr.span
}
Expand Down Expand Up @@ -6203,6 +6226,9 @@ fn build_module_interface(


fn local_binding_for_item(item: Node, source_indices: Map<String, NewlineIndex>) -> TypeBinding? {
if is_namespace_alias_item(item: item, source_indices: source_indices) {
none
} else {
let has_structure = item.connective != NoConnective
if has_structure {
let type_node = Node {
Expand Down Expand Up @@ -6248,6 +6274,7 @@ fn local_binding_for_item(item: Node, source_indices: Map<String, NewlineIndex>)
} else {
none
}
}
}

fn symbol_index_insert_item(
Expand All @@ -6256,14 +6283,34 @@ fn symbol_index_insert_item(
item: Node,
source_indices: Map<String, NewlineIndex>
) -> SymbolIndex {
let with_decl = match local_binding_for_item(item: item, source_indices: source_indices) {
Absent => index
Present { value: binding } =>
symbol_index_insert_decl(
index: index,
module_path: module_path,
binding: binding
)
let with_decl = if is_namespace_alias_item(item: item, source_indices: source_indices) {
match namespace_alias_target_path(item: item, source_indices: source_indices) {
Absent => index
Present { value: target_path } =>
match symbol_index_lookup(index: index, qualified_name: target_path) {
Absent => index
Present { value: target_node } =>
symbol_index_insert_decl(
index: index,
module_path: module_path,
binding: namespace_alias_binding_for_target(
item: item,
target_node: target_node,
source_indices: source_indices
)
)
}
}
} else {
match local_binding_for_item(item: item, source_indices: source_indices) {
Absent => index
Present { value: binding } =>
symbol_index_insert_decl(
index: index,
module_path: module_path,
binding: binding
)
}
}
if item.transport != none && item.children |> count > 0 {
symbol_index_insert_service(
Expand Down Expand Up @@ -6784,11 +6831,40 @@ fn build_type_env(module: ResolvedModule, parent_index: Map<String, TypedModule>
)
let scope_parents = concat(import_parents, [kernel])
let import_diags = flat_map(module.resolved_imports, imp => match map_get(parent_index, imp.module_path) { Present { value: _ } => [] Absent => [make_error_node(diagnostic: InternalError { message: concat("missing parent environment for imported module '", imp.module_path, "' while typechecking '", module_name_str, "'"), span: imp.target_module.value.span }, module_name: module_name_str)] })
let namespace_alias_diags = flat_map(module_items(n: module.module), item =>
if is_namespace_alias_item(item: item, source_indices: source_indices) {
match namespace_alias_target_path(item: item, source_indices: source_indices) {
Absent => []
Present { value: target_path } =>
match symbol_index_lookup(index: symbol_index, qualified_name: target_path) {
Present { value: _ } => []
Absent => [make_error_node(diagnostic: UnresolvedType { name: target_path, span: item.span }, module_name: module_name_str)]
}
}
} else { [] }
)

let local_bindings = fold(module_items(n: module.module), init: empty_map(), f: (acc, item) =>
match local_binding_for_item(item: item, source_indices: source_indices) {
Present { value: binding } => map_insert(acc, intern(table: intern_table, s: binding.name).id, binding)
Absent => acc
if is_namespace_alias_item(item: item, source_indices: source_indices) {
match namespace_alias_target_path(item: item, source_indices: source_indices) {
Absent => acc
Present { value: target_path } =>
match symbol_index_lookup(index: symbol_index, qualified_name: target_path) {
Absent => acc
Present { value: target_node } =>
let binding = namespace_alias_binding_for_target(
item: item,
target_node: target_node,
source_indices: source_indices
)
map_insert(acc, intern(table: intern_table, s: binding.name).id, binding)
}
}
} else {
match local_binding_for_item(item: item, source_indices: source_indices) {
Present { value: binding } => map_insert(acc, intern(table: intern_table, s: binding.name).id, binding)
Absent => acc
}
}
)

Expand Down Expand Up @@ -6887,7 +6963,7 @@ fn build_type_env(module: ResolvedModule, parent_index: Map<String, TypedModule>
BuildTypeEnvResult {
env: final_env,
cache: type_env_cache,
diagnostics: concat(import_diags, resolved_diags),
diagnostics: concat(concat(import_diags, namespace_alias_diags), resolved_diags),
binding_forks: binding_forks
}
}
Expand Down Expand Up @@ -6917,6 +6993,9 @@ fn build_type_env_unresolved(module: ResolvedModule, parent_index: Map<String, T
)
let scope_parents = concat(import_parents, [kernel])
let local_bindings = fold(module_items(n: module.module), init: empty_map(), f: (acc, item) =>
if is_namespace_alias_item(item: item, source_indices: source_indices) {
acc
} else {
let item_ident = intern(table: intern_table, s: authored_name_at(source_indices: source_indices, node: item)).id
let has_structure = item.connective != NoConnective
if has_structure {
Expand All @@ -6933,6 +7012,7 @@ fn build_type_env_unresolved(module: ResolvedModule, parent_index: Map<String, T
} else {
acc
}
}
)
let kernel_cache = type_env_cache_from_bindings(
bindings: kernel_bindings,
Expand Down
10 changes: 10 additions & 0 deletions src/v1/stage0/src/extdeps_languages_dag_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ pub fn dag_item_forms() -> Rc<Vec<Rc<ItemForm>>> {
thread_local! {
static CACHED: Rc<Vec<Rc<ItemForm>>> = {
Rc::new(vec![Rc::new(ItemForm {
kind: ItemFormKind::OtherForm,
keyword: "alias".to_string(),
has_type_params: false,
has_params: false,
has_return_type: false,
return_required: false,
has_uses: false,
body_kind: BodyKind::AliasBody,
}), Rc::new(ItemForm {
kind: ItemFormKind::TypeAliasForm,
keyword: "type".to_string(),
has_type_params: true,
Expand Down Expand Up @@ -145,6 +154,7 @@ pub fn dag_keyword_set() -> Rc<HashMap<String, bool>> {
let mut __m = HashMap::new();
__m.insert("module".to_string(), true);
__m.insert("import".to_string(), true);
__m.insert("alias".to_string(), true);
__m.insert("type".to_string(), true);
__m.insert("fn".to_string(), true);
__m.insert("func".to_string(), true);
Expand Down
3 changes: 3 additions & 0 deletions src/v1/stage0/src/std_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ pub enum BodyKind {
NoBody,
ServiceBody,
ResourceBody,
AliasBody,
}

#[derive(
Expand Down Expand Up @@ -201,6 +202,8 @@ pub struct ServiceBody;
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct ResourceBody;
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct AliasBody;
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct FuncForm;
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct StructForm;
Expand Down
Loading
Loading