Skip to content

Commit

Permalink
maybe broken
Browse files Browse the repository at this point in the history
  • Loading branch information
aspizu committed Oct 13, 2024
1 parent c9381a9 commit bb01341
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 106 deletions.
2 changes: 1 addition & 1 deletion editors/code/syntaxes/goboscript.tmGrammar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ patterns:
- name: keyword
match: "\\b(costumes|sounds|global|variables|lists|nowarp|onflag|onkey|onbackdrop|onloudness|ontimer|on|onclone)\\b"
- name: keyword.control
match: "\\b(if|else|elif|until|forever|repeat|delete|at|add|to|insert|true|false)\\b"
match: "\\b(if|else|elif|until|forever|repeat|delete|at|add|to|insert|true|false|struct|list)\\b"
- name: keyword
match: "\\b(error|warn|breakpoint|local|not|and|or|in|length|round|abs|floor|ceil|sqrt|sin|cos|tan|asin|acos|atan|ln|log|antiln|antilog)\\b"
- name: support.function.builtin
Expand Down
39 changes: 9 additions & 30 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,13 @@ pub struct List {
pub name: SmolStr,
pub span: Span,
pub default: Literals,
pub type_: Type,
pub used: bool,
}

impl List {
pub fn new(name: SmolStr, span: Span, default: Literals) -> Self {
Self { name, span, default, used: false }
pub fn new(name: SmolStr, span: Span, default: Literals, type_: Type) -> Self {
Self { name, span, default, type_, used: false }
}
}

Expand Down Expand Up @@ -308,34 +309,12 @@ pub enum Expr {
Int(i64),
Float(f64),
Str(SmolStr),
Name {
name: SmolStr,
span: Span,
},
Arg {
name: SmolStr,
span: Span,
},
Repr {
repr: Repr,
span: Span,
args: Exprs,
},
UnOp {
op: UnOp,
val: Rrc<Expr>,
},
BinOp {
op: BinOp,
lhs: Rrc<Expr>,
rhs: Rrc<Expr>,
},
Accessor {
symbol_name: SmolStr,
symbol_span: Span,
property_name: SmolStr,
property_span: Span,
},
Name { name: SmolStr, span: Span },
Arg { name: SmolStr, span: Span },
Repr { repr: Repr, span: Span, args: Exprs },
UnOp { op: UnOp, val: Rrc<Expr> },
BinOp { op: BinOp, lhs: Rrc<Expr>, rhs: Rrc<Expr> },
Accessor { val: Rrc<Expr>, property_name: SmolStr, property_span: Span },
}

impl Expr {
Expand Down
167 changes: 101 additions & 66 deletions src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,14 +325,41 @@ where T: Write + Seek
.to_diagnostic(list.span.clone()),
);
}
self.comma(&mut comma)?;
write!(
self,
r#"{}:[{},{}]"#,
json!(*list.name),
json!(*list.name),
json!(list.default)
)?;
match &list.type_ {
Type::Any => {
self.comma(&mut comma)?;
write!(
self,
r#"{}:[{},{}]"#,
json!(*list.name),
json!(*list.name),
json!(list.default)
)?;
}
Type::Struct(struct_name, struct_name_span) => {
let Some(struct_) = sprite.structs.get(struct_name) else {
diags.push(
DiagnosticKind::UnrecognizedStruct {
name: struct_name.clone(),
}
.to_diagnostic(struct_name_span.clone()),
);
continue;
};
for (field_name, _) in &struct_.fields {
self.comma(&mut comma)?;
let resolved_name =
json!(format!("{}.{}", list.name, field_name));
write!(
self,
r#"{}:[{},{}]"#,
resolved_name,
resolved_name,
json!(list.default),
)?;
}
}
}
}
self.write_all(br#"},"broadcasts":{"#)?;
let mut comma = false;
Expand Down Expand Up @@ -1069,74 +1096,82 @@ where T: Write + Seek
write!(self, r#"[1,[10,{}]]"#, json!(**value))
}
}
Expr::Accessor {
symbol_name,
symbol_span,
property_name,
property_span,
} => {
let enum_ = s.sprite.enums.get(symbol_name);
let variable =
s.sprite.vars.get(symbol_name).or_else(|| {
s.proc.and_then(|proc| proc.locals.get(symbol_name))
});
if let Some(enum_) = enum_ {
let index = enum_
.variants
.iter()
.position(|(variant, _)| variant == property_name);
if let Some(index) = index {
write!(self, r#"[1,[10,{index}]]"#)?;
} else {
d.push(
DiagnosticKind::UnrecognizedEnumVariant {
enum_name: symbol_name.clone(),
variant_name: property_name.clone(),
Expr::Accessor { val, property_name, property_span } => {
if !match &*val.borrow() {
Expr::Name { name: symbol_name, span: symbol_span } => {
let enum_ = s.sprite.enums.get(symbol_name);
let variable = s.sprite.vars.get(symbol_name).or_else(|| {
s.proc.and_then(|proc| proc.locals.get(symbol_name))
});
if let Some(enum_) = enum_ {
let index = enum_
.variants
.iter()
.position(|(variant, _)| variant == property_name);
if let Some(index) = index {
write!(self, r#"[1,[10,{index}]]"#)?;
} else {
d.push(
DiagnosticKind::UnrecognizedEnumVariant {
enum_name: symbol_name.clone(),
variant_name: property_name.clone(),
}
.to_diagnostic(property_span.clone()),
);
}
.to_diagnostic(property_span.clone()),
);
}
Ok(())
} else if variable
.is_some_and(|it| matches!(it.type_, Type::Struct { .. }))
{
let type_name = match &variable.unwrap().type_ {
Type::Struct(name, _) => name,
_ => unreachable!(),
};
let struct_ = s.sprite.structs.get(type_name).unwrap();
let found = struct_
.fields
.iter()
.find(|(variant, _)| variant == property_name);
if found.is_some() {
let resolved = self
.resolve_local_field(s, symbol_name, property_name)
.unwrap_or_else(|| {
format!("{}.{}", symbol_name, property_name)
});
let resolved = json!(resolved);
write!(self, r#"[3,[12,{},{}],"#, resolved, resolved)?;
} else {
d.push(
DiagnosticKind::UnrecognizedStructField {
struct_name: symbol_name.clone(),
field_name: property_name.clone(),
Ok(())
} else if variable
.is_some_and(|it| matches!(it.type_, Type::Struct { .. }))
{
let type_name = match &variable.unwrap().type_ {
Type::Struct(name, _) => name,
_ => unreachable!(),
};
let struct_ = s.sprite.structs.get(type_name).unwrap();
let found = struct_
.fields
.iter()
.find(|(variant, _)| variant == property_name);
if found.is_some() {
let resolved = self
.resolve_local_field(s, symbol_name, property_name)
.unwrap_or_else(|| {
format!("{}.{}", symbol_name, property_name)
});
let resolved = json!(resolved);
write!(self, r#"[3,[12,{},{}],"#, resolved, resolved)?;
} else {
d.push(
DiagnosticKind::UnrecognizedStructField {
struct_name: symbol_name.clone(),
field_name: property_name.clone(),
}
.to_diagnostic(property_span.clone()),
);
}
.to_diagnostic(property_span.clone()),
);
self.input_shadow(s, shadow_id, name)
} else {
d.push(
DiagnosticKind::InvalidPropertyAccess {
symbol_name: symbol_name.clone(),
property_name: property_name.clone(),
}
.to_diagnostic(symbol_span.clone()),
);
}
true
}
self.input_shadow(s, shadow_id, name)
} else {
_ => false,
} {
d.push(
DiagnosticKind::InvalidPropertyAccess {
symbol_name: symbol_name.clone(),
property_name: property_name.clone(),
}
.to_diagnostic(symbol_span.clone()),
);
Ok(())
}
Ok(())
}
Expr::Name { name: var, span } => {
if let Some(resolved) =
Expand Down Expand Up @@ -1409,5 +1444,5 @@ where T: Write + Seek
}

fn local_variable_resolved_name(proc: &Proc, name: &SmolStr) -> String {
format!("{}.{}", proc.name, name)
format!("{}@{}", proc.name, name)
}
2 changes: 2 additions & 0 deletions src/lexer/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,6 @@ pub enum Token {
False,
#[token("struct")]
Struct,
#[token("list")]
List,
}
21 changes: 20 additions & 1 deletion src/parser/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ Declr: () = {
},
STRUCT <l:@L> <name:NAME> <r:@R> "{" <fields:SpannedComma<NAME>> "}" => {
sprite.structs.insert(name.clone(), Struct::new(name, l..r, fields));
},
LIST <l:@L> <name:NAME> <r:@R> ";" => {
sprite.lists.insert(name.clone(), List::new(name.clone(), l..r, Default::default(), Type::Any));
},
LIST <tl:@L> <type_:NAME> <tr:@R> <l:@L> <name:NAME> <r:@R> ";" => {
sprite.lists.insert(name.clone(), List::new(name.clone(), l..r, Default::default(), Type::Struct(type_, tl..tr)));
}
}

Expand Down Expand Up @@ -107,7 +113,7 @@ Stmt: Stmt = {
ADD <value:Expr> TO <l:@L> <name:NAME> <r:@R> ";" => Stmt::ListAdd { name, span: l..r, value },
DELETE <l:@L> <name:NAME> <r:@R> ";" => {
if !sprite.lists.contains_key(&name) {
sprite.lists.insert(name.clone(), List::new(name.clone(), l..r, Default::default()));
sprite.lists.insert(name.clone(), List::new(name.clone(), l..r, Default::default(), Type::Any));
}
Stmt::ListDeleteAll { name, span: l..r }
},
Expand Down Expand Up @@ -189,6 +195,7 @@ Expr: Rrc<Expr> = {
}

Term: Rrc<Expr> = {
#[precedence(level="1")]
"(" <Expr> ")",
TRUE => Expr::Int(1).into(),
FALSE => Expr::Int(0).into(),
Expand All @@ -204,14 +211,25 @@ Term: Rrc<Expr> = {
Some(repr) => Ok(Expr::Repr { repr, span: l..r, args }.into()),
None => Err(ParseError::User { error: DiagnosticKind::UnrecognizedReporter(name).to_diagnostic(l..r) }),
},
#[precedence(level="2")]
<l:@L> <e:Term> "[" <i:Expr> "]" <r:@R> => BinOp::Of.to_expr(e, i).into(),
#[precedence(level="3")]
<sl:@L> <symbol_name:NAME> <sr:@R> "." <pl:@L> <property_name:NAME> <pr:@R> =>
Expr::Accessor {
symbol_name,
symbol_span: sl..sr,
property_name,
property_span: pl..pr
}.into(),
#[precedence(level="4")]
<sl:@L> <list_name:NAME> <sr:@R> "[" <i:Expr> "]" "." <pl:@L> <property_name:NAME> <pr:@R> =>
Expr::ListAccessor {
list_name,
list_span: sl..sr,
index: i,
property_name,
property_span: pl..pr
}.into(),
}

Exprs: Vec<Rrc<Expr>> = <Comma<Expr>>;
Expand Down Expand Up @@ -331,5 +349,6 @@ extern {
TRUE => Token::True,
FALSE => Token::False,
STRUCT => Token::Struct,
LIST => Token::List,
}
}
Loading

0 comments on commit bb01341

Please sign in to comment.