Skip to content

Commit

Permalink
Implement round trip dumping of the new object format
Browse files Browse the repository at this point in the history
Creates a directory containing a full dump of all the objects, 1 object
per file.
Accompanied by myriads of fixes and improvements to the parser and its
format.
Includes a test which imports a full JHCore, dumps it out in the new
format, and imports it back in.
  • Loading branch information
rdaum committed Jan 30, 2025
1 parent f706011 commit d2d70e7
Show file tree
Hide file tree
Showing 19 changed files with 1,193 additions and 526 deletions.
3 changes: 2 additions & 1 deletion bacon.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ command = [
"development.db",
"--textdump",
"minimal-core",
"--dirdump-format",
"--import-dirdump-format",
"--export-dirdump-format",
"--textdump-out",
"textdumps",
"--checkpoint-interval-seconds",
Expand Down
24 changes: 23 additions & 1 deletion crates/common/src/model/match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl Preposition {
match s {
"with/using" | "with" | "using" => Some(Self::WithUsing),
"at/to" | "at" | "to" => Some(Self::AtTo),
"in front of" => Some(Self::InFrontOf),
"in front of" | "in-front-of" => Some(Self::InFrontOf),
"in/inside/into" | "in" | "inside" | "into" => Some(Self::IntoIn),
"on top of/on/onto/upon" | "on top of" | "on" | "onto" | "upon" => {
Some(Self::OnTopOfOn)
Expand Down Expand Up @@ -126,6 +126,28 @@ impl Preposition {
Self::OffOf => "off/off of",
}
}

/// Output only one preposition, instead of the full break down.
/// For output in objdefs, etc where space-separation is required
pub fn to_string_single(&self) -> &str {
match self {
Self::WithUsing => "with",
Self::AtTo => "at",
Self::InFrontOf => "in-front-of",
Self::IntoIn => "in",
Self::OnTopOfOn => "on",
Self::OutOf => "from",
Self::Over => "over",
Self::Through => "through",
Self::Under => "under",
Self::Behind => "behind",
Self::Beside => "beside",
Self::ForAbout => "for",
Self::Is => "is",
Self::As => "as",
Self::OffOf => "off",
}
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Encode, Decode)]
Expand Down
4 changes: 2 additions & 2 deletions crates/common/src/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ pub use crate::model::objects::{ObjAttr, ObjAttrs, ObjFlag, ObjectRef};
pub use crate::model::objset::{ObjSet, ObjSetIter};
pub use crate::model::permissions::Perms;
pub use crate::model::propdef::{PropDef, PropDefs};
pub use crate::model::props::{PropAttr, PropAttrs, PropFlag, PropPerms};
pub use crate::model::props::{prop_flags_string, PropAttr, PropAttrs, PropFlag, PropPerms};
pub use crate::model::r#match::{ArgSpec, PrepSpec, Preposition, VerbArgsSpec};
pub use crate::model::verbdef::{VerbDef, VerbDefs};
pub use crate::model::verbs::{BinaryType, VerbAttr, VerbAttrs, VerbFlag, Vid};
pub use crate::model::verbs::{verb_perms_string, BinaryType, VerbAttr, VerbAttrs, VerbFlag, Vid};
pub use crate::model::world_state::{WorldState, WorldStateSource};
use crate::AsByteBuffer;
use bincode::{Decode, Encode};
Expand Down
14 changes: 14 additions & 0 deletions crates/common/src/model/props.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ impl PropFlag {
}
}

pub fn prop_flags_string(flags: BitEnum<PropFlag>) -> String {
let mut s = String::new();
if flags.contains(PropFlag::Read) {
s.push('r');
}
if flags.contains(PropFlag::Write) {
s.push('w');
}
if flags.contains(PropFlag::Chown) {
s.push('c');
}
s
}

#[derive(Debug, Clone, Copy, Primitive)]
pub enum PropAttr {
Value = 0,
Expand Down
18 changes: 18 additions & 0 deletions crates/common/src/model/verbs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,24 @@ impl LayoutAs<u8> for VerbFlag {
}
}

pub fn verb_perms_string(perms: BitEnum<VerbFlag>) -> String {
let mut perms_string = String::new();
if perms.contains(VerbFlag::Read) {
perms_string.push('r');
}
if perms.contains(VerbFlag::Write) {
perms_string.push('w');
}
if perms.contains(VerbFlag::Exec) {
perms_string.push('x');
}
if perms.contains(VerbFlag::Debug) {
perms_string.push('d');
}

perms_string
}

impl VerbFlag {
pub fn parse_str(s: &str) -> Option<BitEnum<Self>> {
let mut flags: u8 = 0;
Expand Down
2 changes: 1 addition & 1 deletion crates/compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub use crate::decompile::program_to_tree;
pub use crate::labels::{JumpLabel, Label, Offset};
pub use crate::names::{Name, UnboundNames};
pub use crate::objdef::{
compile_object_definitions, ObjDefParseError, ObjPropDef, ObjPropSet, ObjVerbDef,
compile_object_definitions, ObjDefParseError, ObjPropDef, ObjPropOverride, ObjVerbDef,
ObjectDefinition,
};
pub use crate::opcode::{Op, ScatterLabel};
Expand Down
34 changes: 23 additions & 11 deletions crates/compiler/src/moo.pest
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ cpp_comment = @{ "//" ~ (!NEWLINE ~ ANY)* }

WHITESPACE = _{ " " | "\t" | NEWLINE | comment }

// And prepositions can't just be IDENT, because that excludes keywords... like "for"
PREP_CHARACTERS = @{ ASCII_ALPHA+ }
PROPCHARS = @{ ASCII_ALPHANUMERIC | "_" }

// "Objects files" are an alternate import format for reading cores or databases, that is designed to be readable and
// editable by regular tools.
objects_file = { SOI ~ object_definition* ~ EOI }
Expand All @@ -271,19 +275,27 @@ write_attr = { "writeable" ~ ":" ~ boolean }

boolean = { "true" | "false" }

verb_decl = { ^"verb" ~ verb_names ~ "(" ~ verbargspec ~ ")" ~ owner_attr ~ flags_attr ~ verb_statements }
verb_names = { (verb_name ~ ("," ~ verb_name)*) }
verb_decl = { ^"verb" ~ verb_name ~ "(" ~ verbargspec ~ ")" ~ owner_attr ~ flags_attr ~ verb_statements }
verb_statements = { statements ~ "endverb" }
verb_name = { ident ~ "*"? }
verbargspec = {argspec ~ ident ~ argspec }

// A verb name for a textdump is actually more permissive than ident, since you can embed them in :("string") style dispatch
// Beyond wildcards, they also permit special characters like #, %, etc.
// So we'll accept either a string literal, or a single alphanumeric-ish ident
verb_name = { string | verbident }
verbident = { PROPCHARS+ }

verbargspec = {argspec ~ PREP_CHARACTERS ~ argspec }
argspec = {"this" | "none" | "any"}
flags_attr = {"flags" ~ ":" ~ ident}
flagchars = @{ ASCII_ALPHA* }
flags_attr = {"flags" ~ ":" ~ "\"" ~ flagchars ~ "\"" }

literal = { atom | literal_map | literal_list }
literal = { atom | literal_map | literal_list | literal_flyweight }
literal_map = { ("[" ~ (literal ~ "->" ~ literal) ~ ("," ~ literal ~ "->" ~ literal)* ~ "]") | "[]" }
literal_list = { ("{" ~ literallist ~ "}") | "{}" }
literallist = { literal ~ ("," ~ literal)* }

prop_def = {"property" ~ ident ~ propinfo ~ ("=" ~ literal)? ~ ";" }
prop_set = {"override" ~ ident ~ propinfo? ~ ("=" ~ literal)? ~ ";" }
literal_list = { ("{" ~ literal ~ ("," ~ literal)* ~ "}") | "{}" }
literal_flyweight = { "<" ~ literal ~ ("," ~ literal_flyweight_slots)? ~ ("," ~ literal_flyweight_contents)? ~ ">" }
literal_flyweight_slots = { "[" ~ (ident ~ "->" ~ literal) ~ ("," ~ ident ~ "->" ~ literal)* ~ "]" }
literal_flyweight_contents = { "{" ~ (literal ~ ("," ~ literal)*)? ~ "}" }
prop_def = {"property" ~ propname ~ propinfo ~ ("=" ~ literal)? ~ ";" }
prop_set = {"override" ~ propname ~ propinfo? ~ ("=" ~ literal)? ~ ";" }
propname = { string | PROPCHARS+ }
propinfo = {"(" ~ owner_attr ~ "," ~ flags_attr ~ ")"}
Loading

0 comments on commit d2d70e7

Please sign in to comment.