Skip to content

Latest commit

 

History

History
174 lines (127 loc) · 7.15 KB

API.adoc

File metadata and controls

174 lines (127 loc) · 7.15 KB

Stable(r) API

General

SMM stores the state of a Metamath database as an instance of the MMOM.Database class. A database represents a sequence of zero or more individually well-formed statements of the Metamath language. A database can legally represent states which are jointly invalid, such as a database containing a proof but not some of the steps the proof depends on. Individual statements are represented by instances of MMOM.Statement. A statement is born into a database, and thereafter is not (observably) modified except to remove it. Databases are modified by calling methods on the database to insert statements, remove statements, and replace statements with modified versions.

Statements in SMM are the statements defined in the Metamath specification, plus SMM-specific statement types COMMENT, INCLUDE, BOGUS, METACOMMENT, and EOF; these statement types have no effect on the mathematical content of the database, but serve to hold text during parsing that does not naturally correspond to any statement. SMM always knows the character data corresponding to a statement. It is impossible to create a statement without making some decision about the whitespace that would be used to write that statement to a file. Statements own their leading whitespace. Whitespace at the end of the file is owned by the special EOF statement. Comments are treated as whitespace if found inside statements, but are promoted to statements in their own right if they appear between statements.

Parsing

import { parseSync } from 'smm';
database = parseSync('filename', '$( file content $)');

Call parseSync with two strings to parse a database which is already loaded as a string. Returns a MMOM.Database instance. The filename will be used for error messages (also, $[ will ignore that filename but give errors for all others). Never throws, returns errors in the database object.

database = parseSync('file1',
    new Map().set('file1','$[ file2 $]').set('file2',''));

The second argument to parseSync may be a Map if multiple files are used.

database = parseSync('file1', filename => 'foo');

The second argument to parseSync may be a function, which will be passed a file name and must return a string or throw an exception. Exceptions will be wrapped into failed-to-read errors.

import { parseAsync } from 'smm'
promise = parseAsync('file1', filename =>
    fetch(filename).then(rpy => rpy.text())).then(db => ... );

parseAsync functions like parseSync except that only the function form is supported, the function is expected to return a promise, and a promise is returned at the end. As parseSync never throws, the promise returned from parseAsync never rejects.

The parsing process will attempt to recover from arbitrary errors in the source, and the resulting database will contain only valid statements. Some statements will be repaired, those which cannot will be turned into BOGUS type statements. However, a database with parsing errors cannot be modified, due to the difficulty in updating the parsing error data after changes.

text = database.text

Convert a database back into text, to save in a file. Does not support $[ $].

Statements

count = database.statementCount;
statement = database.statement(42);

A database has a statementCount property and a statement reader method. Currently all database access is mediated by statement indices. This is problematic as when an insert or delete is done, statement indices are invalidated. It is likely that a future version of SMM will use another technique to record statement positions; statement(N) will still be supported, but will suffer an O(n) penalty to build an index.

Statements are immutable. To change a database, splice in new statements; do not attempt to modify existing ones.

import { MMOMStatement } from 'smm';
statement.type === MMOMStatement.OPEN;
statement.type === MMOMStatement.CLOSE;
statement.type === MMOMStatement.CONSTANT;
statement.type === MMOMStatement.VARIABLE;
statement.type === MMOMStatement.DISJOINT;
statement.type === MMOMStatement.ESSENTIAL;
statement.type === MMOMStatement.FLOATING;
statement.type === MMOMStatement.AXIOM;
statement.type === MMOMStatement.PROVABLE;

Statements have a type property, which is equal to the constants above for real statements. Fake statements also have types, but their number and roles are not currently considered stable.

string = statement.label;
arrayString = statement.math;
arrayString = statement.proof;

Accessors for the fundamental parts of a statement. math and proof may be null on statement types for which they are not applicable; when they are applicable, they will always be present even if empty.

text = statement.raw;         // the while statement
text = statement.mathText;    // inside $acefpv $=.
text = statement.proofText;   // inside $= $.
text = statement.commentText; // inside $( $), COMMENT only

Accessors for portions of a statement, identified but with whitespace and embedded comments preserved.

index = statement.index;
database = statement.database;
statement === database.statement(index);

A statement which is in a database knows its database and index.

database.replaceStatements(3,4,'');
database.replaceStatements(2,2,' $( A NEW COMMENT $)');
database.replaceMathString(database.statement(2), ' 2 + 2 ');
database.replaceProofString(database.statement(2), ' ? ');

Databases can be modified by replacing a run of statements with a new run of statements. Several rules apply to ensure that the new database can still be parsed.

Scoper

This module calculates scopes and symbol tables.

let sym = database.scoper.lookup('ruc');
database.verifier.errors(sym.labelled);

Symbol table entries are returned as objects with slots for different types of usage of symbols. Currently only labelled (find the statement with this label) has API status.

Verifier

This is the standard-mode verifier; it does not exploit statement parsing (that works only for set.mm). It implements the common error checking protocol but has no other API.

Metadata

Metadata from the $t comment can be accessed using the metadata analyzer.

title = database.metadata.param('htmltitle');
andsign = database.metadata.tokenDef('htmldef', '/\\');

Both methods return null if not defined.

Errors

array_of_errors = database.scoper.errors(statement);
map_of_errors = database.scoper.allErrors;

array_of_errors = database.verifier.errors(statement);
map_of_errors = database.verifier.allErrors;

Several analyzers have the capability to generate warnings or errors while analyzing the database. These analyzers implement a common API: errors fetches a list of errors for a specific statement, allErrors fetches a map with error data for each statement with at least one error.

array_of_errors = database.scanner.errors;

Scanner errors are reported differently because they cannot generally be linked to a statement.

process.stdout.write( error.toConsoleString(), 'utf8' );

Renders an error as a string containing newlines for human consumption.