Skip to content

Commit

Permalink
finish importing all tests + receiver parenthesis
Browse files Browse the repository at this point in the history
  • Loading branch information
ivojawer committed Nov 10, 2023
1 parent ae3b6c9 commit 0b01554
Show file tree
Hide file tree
Showing 5 changed files with 834 additions and 69 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"test:sanity": "npm run test:wtest -- --root language/test/sanity",
"test:validations": "mocha --parallel -r ts-node/register/transpile-only test/validator.test.ts",
"test:wtest": "mocha --delay -t 10000 -r ts-node/register/transpile-only test/wtest.ts",
"test:printer": "mocha --parallel -r ts-node/register/transpile-only test/printer.test.ts",
"test:printer": "mocha --parallel -r ts-node/register/transpile-only test/printer-tests/*.test.ts",
"prepublishOnly": "npm run build && npm test",
"postpublish": "git tag v$npm_package_version && git push --tags",
"prepack": "npm run build"
Expand Down
1 change: 0 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,4 @@ export const KEYWORDS = {
FIXTURE: 'fixture',
PROGRAM: 'program',
PACKAGE: 'package',

} as const
61 changes: 49 additions & 12 deletions src/printer/print.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IDoc, append, braces, choice, enclose, hang as nativeHang, intersperse, lineBreak, lineBreaks, indent as nativeIndent, nest as nativeNest, parens, render, softBreak, softLine, align } from 'prettier-printer'
import { KEYWORDS, LIST_MODULE, SET_MODULE } from '../constants'
import { KEYWORDS, LIST_MODULE, PREFIX_OPERATORS, SET_MODULE } from '../constants'
import { List, match, when, notEmpty, isEmpty } from '../extensions'
import { Assignment, Body, Class, Describe, Expression, Field, If, Import, Literal, Method, Mixin, NamedArgument, New, Node, Package, Parameter, ParameterizedType, Program, Reference, Return, Self, Send, Sentence, Singleton, Super, Test, Variable } from '../model'
import { Assignment, Body, Class, Describe, Expression, Field, If, Import, Literal, Method, Mixin, Name, NamedArgument, New, Node, Package, Parameter, ParameterizedType, Program, Reference, Return, Self, Send, Sentence, Singleton, Super, Test, Variable } from '../model'
import { DocTransformer, WS, body, enclosedList, infixOperators, listEnclosers, listed, setEnclosers, stringify } from './utils'

type PrintSettings = {
Expand Down Expand Up @@ -74,7 +74,7 @@ const format: FormatterWithContext<Node> = context => node => {
}

const formatPackage: FormatterWithContext<Package> = context => node => {
return [node.imports.length > 0 ? [intersperse(lineBreak, node.imports.map(format(context))), lineBreaks] : [], intersperse(
return [notEmpty(node.imports) ? [intersperse(lineBreak, node.imports.map(format(context))), lineBreaks] : [], intersperse(
lineBreaks,
node.members.map(format(context))
)]
Expand Down Expand Up @@ -268,7 +268,7 @@ const formatMixin: FormatterWithContext<Mixin> =context => node => {
KEYWORDS.MIXIN,
WS,
node.name,
node.supertypes.length > 0 ? [WS, KEYWORDS.INHERITS, WS, intersperse([WS, KEYWORDS.MIXED_AND, WS], node.supertypes.map(format(context)))] : [],
notEmpty(node.supertypes) ? [WS, KEYWORDS.INHERITS, WS, intersperse([WS, KEYWORDS.MIXED_AND, WS], node.supertypes.map(format(context)))] : [],
]

return [declaration, WS, formatModuleMembers(context)(node.members)]
Expand All @@ -277,7 +277,7 @@ const formatMixin: FormatterWithContext<Mixin> =context => node => {
const formatParameterizedType: FormatterWithContext<ParameterizedType> =
context => node => [
node.reference.name,
node.args.length > 0 ?
notEmpty(node.args) ?
[WS, enclosedList(context.nest)(parens, node.args.map(format(context)))] :
[],
]
Expand All @@ -294,7 +294,7 @@ const formatSingleton: FormatterWithContext<Singleton> = context => (node: Singl

const formatClosure: FormatterWithContext<Singleton> = context => node => {
const applyMethod = node.members[0] as Method
const parameters = applyMethod.parameters.length > 0 ?
const parameters = notEmpty(applyMethod.parameters) ?
[WS, listed(applyMethod.parameters.map(format(context))), WS, '=>']
: []

Expand All @@ -320,7 +320,7 @@ const formatWKO: FormatterWithContext<Singleton> = context => node => {
return intersperse(WS, [...formatted, members])
}

const inherits = (node: Singleton | Class) => node.supertypes.length > 0
const inherits = (node: Singleton | Class) => notEmpty(node.supertypes)

const formatInheritance: FormatterWithContext<Singleton | Class> = (context: PrintContext) => node => {
return intersperse(WS, [
Expand All @@ -333,9 +333,19 @@ const formatInheritance: FormatterWithContext<Singleton | Class> = (context: Pri
// SEND FORMATTERS

const formatSend: FormatterWithContext<Send> = context => node => {
return infixOperators.includes(node.message) ?
formatInfixSend(context)(node)
: formatDotSend(context)(node)
let formatter: FormatterWithContext<Send>

if(isInfixOperator(node)) {
formatter = formatInfixSend
} else if(
isPrefixOperator(node)
) {
formatter = formatPrefixSend
} else {
formatter = formatDotSend
}

return formatter(context)(node)
}

const formatDotSend: FormatterWithContext<Send> = context => node => [
Expand All @@ -353,10 +363,16 @@ const formatInfixSend: FormatterWithContext<Send> = context => node => {
])
}

const formatPrefixSend: FormatterWithContext<Send> = context => node => {
return [prefixOperatorByMessage[node.message], addParenthesisIfNeeded(context, node.receiver)]
}

function addParenthesisIfNeeded(context: PrintContext, expression: Expression): IDoc {
// ToDo: add more cases where parenthesis aren't needed
const formatted = format(context)(expression)
return expression.is(Send) && infixOperators.includes(expression.message) ? enclose(parens, formatted) : formatted
return expression.is(Send) && (isInfixOperator(expression) || isPrefixOperator(expression)) ?
enclose(parens, formatted) :
formatted
}


Expand Down Expand Up @@ -402,4 +418,25 @@ const formatModuleMembers = (context: PrintContext) => (members: List<Field | Me
// assignment operations
const canBeAbbreviated = (node: Assignment): node is Assignment & {value: Send & {message: keyof typeof assignmentOperationByMessage}} => node.value.is(Send) && node.value.receiver.is(Reference) && node.value.receiver.name === node.variable.name && node.value.message in assignmentOperationByMessage

const assignmentOperationByMessage = { '||':'||=', '/':'/=', '-':'-=', '+':'+=', '*':'*=', '&&':'&&=', '%':'%=' } as const
const assignmentOperationByMessage = { '||':'||=', '/':'/=', '-':'-=', '+':'+=', '*':'*=', '&&':'&&=', '%':'%=' } as const

// send utils

/*
* ToDo: safe way of telling if this is a parser-generated message or a user-defined one
* e.g. x.negate() shouldnt be formatted to !x
*/
const isPrefixOperator = (node: Send): boolean =>
Object.values(PREFIX_OPERATORS).includes(node.message) &&
isEmpty(node.args)

const isInfixOperator = (node: Send): boolean =>
infixOperators.includes(node.message) &&
node.args.length === 1

//ToDo: missing 'not'
const prefixOperatorByMessage: Record<Name, Name> = {
'negate': '!',
'invert': '-',
'plus': '+',
}
Loading

0 comments on commit 0b01554

Please sign in to comment.