;;----------------------------------------------------------------------------;;
;;  Align the position of the textbox in familiars menu
;;  Copyright 2014 Benito Palacios (aka pleonex)
;;
;;  Licensed under the Apache License, Version 2.0 (the "License");
;;  you may not use this file except in compliance with the License.
;;  You may obtain a copy of the License at
;;
;;      http://www.apache.org/licenses/LICENSE-2.0
;;
;;  Unless required by applicable law or agreed to in writing, software
;;  distributed under the License is distributed on an "AS IS" BASIS,
;;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;  See the License for the specific language governing permissions and
;;  limitations under the License.
;;----------------------------------------------------------------------------;;

;; # FAMILIAR DESCRIPTION #
.org 020B6770h
MOV     r4, #0x9A       ; Y Position: original 0x97
.org 020B677Ch
MOV     r1, #8          ; X Position: original 0x08

;; # FAMILIAR OBJECTS #
.org 020B6604h
MOV     r1, #0x73       ; X Position: Original 0x74
ADD     r2, r2, #0x6B   ; Y Position: Original 0x6B

Fix familiar money give number position

;;----------------------------------------------------------------------------;;
;;  Align the position of the textbox in familiars menu
;;  Copyright 2014 Benito Palacios (aka pleonex)
;;
;;  Licensed under the Apache License, Version 2.0 (the "License");
;;  you may not use this file except in compliance with the License.
;;  You may obtain a copy of the License at
;;
;;      http://www.apache.org/licenses/LICENSE-2.0
;;
;;  Unless required by applicable law or agreed to in writing, software
;;  distributed under the License is distributed on an "AS IS" BASIS,
;;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;  See the License for the specific language governing permissions and
;;  limitations under the License.
;;----------------------------------------------------------------------------;;

.arm

;; # FAMILIAR DESCRIPTION #
.org 020B6770h
MOV     r4, #0x9A       ; Y Position: original 0x97
.org 020B677Ch
MOV     r1, #8          ; X Position: original 0x08

;; # FAMILIAR OBJECTS #
.org 020B6604h
MOV     r1, #0x73       ; X Position: Original 0x74
ADD     r2, r2, #0x6B   ; Y Position: Original 0x6B

;; # MONEY GIVEN #
.org 020B671Ch
MOV R1, #0xCD + 9       ; X Position


;Testname=noerr; Arguments=-felf64 -ogotoff64.o; Files=stdout stderr gotoff64.o
;Testname=err; Arguments=-DERROR -felf64 -ogotoff64.o; Files=stdout stderr gotoff64.o

	bits 64
	default rel

	extern foo

	mov r15,[foo wrt ..got]
	lea r12,[foo wrt ..got]
%ifdef ERROR
	lea rax,[foo wrt ..gotoff]
	mov rax,[foo wrt ..gotoff]
%endif

	default abs

	mov r15,[foo wrt ..got]
	lea r12,[foo wrt ..got]
	mov rax,[qword foo wrt ..got]
%ifdef ERROR
	lea rax,[foo wrt ..gotoff]
	mov rax,[foo wrt ..gotoff]
%endif
	mov rax,[qword foo wrt ..gotoff]


;;----------------------------------------------------------------------------;;
;;  Align the position of the textbox in the casino dialogs
;;  Copyright 2014 Benito Palacios (aka pleonex)
;;
;;  Licensed under the Apache License, Version 2.0 (the "License");
;;  you may not use this file except in compliance with the License.
;;  You may obtain a copy of the License at
;;
;;      http://www.apache.org/licenses/LICENSE-2.0
;;
;;  Unless required by applicable law or agreed to in writing, software
;;  distributed under the License is distributed on an "AS IS" BASIS,
;;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;  See the License for the specific language governing permissions and
;;  limitations under the License.
;;----------------------------------------------------------------------------;;

; Money number
.arm
.org 0x02134F78
  MOV     R1, #0x16     ; X pos, original 0x8

Move number of casino coins

;;----------------------------------------------------------------------------;;
;;  Align the position of the textbox in the casino dialogs
;;  Copyright 2014 Benito Palacios (aka pleonex)
;;
;;  Licensed under the Apache License, Version 2.0 (the "License");
;;  you may not use this file except in compliance with the License.
;;  You may obtain a copy of the License at
;;
;;      http://www.apache.org/licenses/LICENSE-2.0
;;
;;  Unless required by applicable law or agreed to in writing, software
;;  distributed under the License is distributed on an "AS IS" BASIS,
;;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;  See the License for the specific language governing permissions and
;;  limitations under the License.
;;----------------------------------------------------------------------------;;

; Money number
.arm
.org 0x02134F78
  MOV     R1, #0x16     ; X pos, original 0x8

; Number of coins
.org 0x02134FB0
  MOV     R1, #0x6E     ; X pos, original 0x60


;;----------------------------------------------------------------------------;;
;;  Align the position of the textbox in team menu
;;  Copyright 2015 Benito Palacios (aka pleonex)
;;
;;  Licensed under the Apache License, Version 2.0 (the "License");
;;  you may not use this file except in compliance with the License.
;;  You may obtain a copy of the License at
;;
;;      http://www.apache.org/licenses/LICENSE-2.0
;;
;;  Unless required by applicable law or agreed to in writing, software
;;  distributed under the License is distributed on an "AS IS" BASIS,
;;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;  See the License for the specific language governing permissions and
;;  limitations under the License.
;;----------------------------------------------------------------------------;;

.arm

;; Character face icon
.org 0x02130478
  ADD     R2, R2, #0x19 - 1     ; Y position

Move health state in team menu

;;----------------------------------------------------------------------------;;
;;  Align the position of the textbox in team menu
;;  Copyright 2015 Benito Palacios (aka pleonex)
;;
;;  Licensed under the Apache License, Version 2.0 (the "License");
;;  you may not use this file except in compliance with the License.
;;  You may obtain a copy of the License at
;;
;;      http://www.apache.org/licenses/LICENSE-2.0
;;
;;  Unless required by applicable law or agreed to in writing, software
;;  distributed under the License is distributed on an "AS IS" BASIS,
;;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;  See the License for the specific language governing permissions and
;;  limitations under the License.
;;----------------------------------------------------------------------------;;

.arm

;; Character face icon
.org 0x02130478
  ADD     R2, R2, #0x19 - 1     ; Y position

;; Health state
.org 0x02130A08
  MOV     R2, #0x2A + 1         ; Y position


.file	"context.asm"
	.text
	.align	2
	.global	kernel_enter
	.type	kernel_enter, %function
kernel_enter:
	mov	r2, lr
	mrs	r3, spsr

	msr	cpsr, #0x9F 		/* system */
	stmfd	sp!, {r0, r2-r12, lr}
	mov	r2, sp
	msr	cpsr, #0x93 		/* supervisor */
	ldmfd   sp!, {r4-r12, lr}
/*	mov     sp, #0x1000 */
	b	syscall_handle (PLT)
	.size	kernel_enter, .-kernel_enter

	.align	2
	.global	kernel_exit
	.type	kernel_exit, %function
kernel_exit:
	@ r0 holds address of user stack
	stmfd	sp!, {r4-r12, lr}

	msr	cpsr, #0x9F		/* System */
	mov	sp, r0
	ldmfd	sp!, {r0, r2-r12, lr}
	msr	cpsr, #0x93		/* Supervisor */

	msr	spsr, r3
	movs	pc, r2
	.size	kernel_exit, .-kernel_exit

Set the stack-less kernel stack to a safe value

.file	"context.asm"
	.text
	.align	2
	.global	kernel_enter
	.type	kernel_enter, %function
kernel_enter:
	mov	r2, lr
	mrs	r3, spsr

	msr	cpsr, #0x9F 		/* system */
	stmfd	sp!, {r0, r2-r12, lr}
	mov	r2, sp
	msr	cpsr, #0x93 		/* supervisor */
	ldmfd   sp!, {r4-r12, lr}
/*	mov     sp, #0x100000 */
	b	syscall_handle (PLT)
	.size	kernel_enter, .-kernel_enter

	.align	2
	.global	kernel_exit
	.type	kernel_exit, %function
kernel_exit:
	@ r0 holds address of user stack
	stmfd	sp!, {r4-r12, lr}

	msr	cpsr, #0x9F		/* System */
	mov	sp, r0
	ldmfd	sp!, {r0, r2-r12, lr}
	msr	cpsr, #0x93		/* Supervisor */

	msr	spsr, r3
	movs	pc, r2
	.size	kernel_exit, .-kernel_exit


# Example code, just demonstrating each instruction
  add $2 $0
  sub $3 $1
  rand $4 5
label:
  load $6 $7
  store $8 $9
  jal label
  jr $10
  beq $11 label
  bgt $12 label
  set $13 $14
  seti $15 16


x0	= 0
ra	= 1
dsp	= 2
rsp	= 3
gp	= 4
gvp	= 5
x16	= 16
x17	= 17
x18	= 18

	include	"sdtest.asm"

	; exit the emulator.

emu_exit:
	andi	x16, x16, 255
	slli	x16, x16, 8
	addi	rsp, rsp, -8
	sd	x16, 0(rsp)
	csrrw	x0, rsp, $780
	jal	x0, *

	; Initialize the BSPL runtime environment.
	; Then, kick off our tests.

_cold:	addi	rsp, x0, $400
	add	dsp, rsp, rsp
	add	gvp, dsp, dsp
	jal	x0, _

	; CPU cold boots here.

	adv	$FFF00, $CC
	jal	x0, _cold

Make work with new BSPL ABI reqs

zero	= 0
ra	= 1
dsp     = 2    ; Data stack pointer.
rsp     = 3    ; Return stack pointer.
gvp     = 4    ; Global variables pointer.
gp	= 13

dr16	= 5
dr17	= 6
dr18	= 7
dr19	= 8
dr20	= 9
dr21	= 10
dr22	= 11
dr23	= 12

x0	= 0
x16	= 16
x17	= 17
x18	= 18

	include	"sdtest.asm"

	; exit the emulator.

emu_exit:
	andi	x16, x16, 255
	slli	x16, x16, 8
	addi	rsp, rsp, -8
	sd	x16, 0(rsp)
	csrrw	x0, rsp, $780
	jal	x0, *

	; Initialize the BSPL runtime environment.
	; Then, kick off our tests.

_cold:	addi	rsp, x0, $400
	add	dsp, rsp, rsp
	add	gvp, dsp, dsp
	jal	x0, _

	; CPU cold boots here.

	adv	$FFF00, $CC
	jal	x0, _cold


Implement yes in NASM for Mac OS X 64-bit

global _main
global _start
extern _puts

section .text
_main:
  add rsi, 8
_start:
  push rdi
  push rsi
comp:
  sub rsp, 8
  cmp rdi, 1
  jg nz
  je zero
nz:
  mov rdi, [rsi]
  jmp loop
zero:
  mov rdi, y
loop:
  call _puts
  add rsp, 8
  pop rsi
  pop rdi
  jmp _start
  ret

section .data
y: db 'y'


Add patch to prevent softlocks entering lighthouse from wrong door

.nds
.relativeinclude on
.erroronwarning on

; If the player enters the lighthouse from one of the top doors while Brachyura is still alive, they would normally get softlocked.
; This patch teleports the player to the bottom of the room in that case so they can fight Brachyura as normal.
; Also, if the player enters it from the bottom right door the wall there would softlock the player and prevent them from entering, so that wall is removed.

@Overlay86Start equ 0x022EB1A0
@FreeSpace equ 0x022EB1A0

.open "ftc/overlay9_53", 022C1FE0h

.org 0x022C3A68 ; Code that runs if misc flag 0 is not set, before initializing the breakable ceilings.
  b @TeleportPlayerIfAtTop

.org 0x022C331C ; Code that calls GetEntitySlot to create the right wall.
  mov r0, 0h ; Don't create the right wall.

.close

.open "ftc/overlay9_86", @Overlay86Start ; Free space overlay

.org @FreeSpace
@TeleportPlayerIfAtTop:
  ldr r0, =02109850h
  ldr r1, [r0, 4h] ; Load player's Y
  cmp r1, 9C0h*1000h
  movlt r2, 0A70h*1000h
  strlt r2, [r0, 4h] ; If the player's Y is < 9C0 teleport them to the bottom of the room. This is in case they entered from one of the top doors.
  movlt r2, 80h*1000h
  strlt r2, [r0] ; Also change the player's X to be in the middle of the room.

  ldr r0, =022CD3F4h ; Replaces the line of code we overwrote to jump to free space
  b 022C3A6Ch ; Return
  .pool

.close


;;----------------------------------------------------------------------------;;
;;  Align the position of the textbox in the effect of items
;;  Copyright 2014 Benito Palacios (aka pleonex)
;;
;;  Licensed under the Apache License, Version 2.0 (the "License");
;;  you may not use this file except in compliance with the License.
;;  You may obtain a copy of the License at
;;
;;      http://www.apache.org/licenses/LICENSE-2.0
;;
;;  Unless required by applicable law or agreed to in writing, software
;;  distributed under the License is distributed on an "AS IS" BASIS,
;;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;  See the License for the specific language governing permissions and
;;  limitations under the License.
;;----------------------------------------------------------------------------;;

.thumb
.org 0x02117D4E
  MOV    R1, #0x60 ; X POS -> Original 0x62

Move slot color in item menu

;;----------------------------------------------------------------------------;;
;;  Align the position of the textbox in the effect of items
;;  Copyright 2014 Benito Palacios (aka pleonex)
;;
;;  Licensed under the Apache License, Version 2.0 (the "License");
;;  you may not use this file except in compliance with the License.
;;  You may obtain a copy of the License at
;;
;;      http://www.apache.org/licenses/LICENSE-2.0
;;
;;  Unless required by applicable law or agreed to in writing, software
;;  distributed under the License is distributed on an "AS IS" BASIS,
;;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;  See the License for the specific language governing permissions and
;;  limitations under the License.
;;----------------------------------------------------------------------------;;

.thumb
;; Item effect
.org 0x02117D4E
  MOV    R1, #0x60 ; X POS -> Original 0x62

;; Slot color
.org 0x021170DE
  MOV    R1, #0x9E - 4 ; X POS


Fix BR 1490407: size of the second operand of LAR/LSL

bits 64

	lar ax,bx
	lar ax,[rsi]
	lar ax,word [rsi]
	lar eax,bx
	lar eax,[rsi]
	lar eax,word [rsi]
	lar rax,bx
	lar rax,[rsi]
	lar rax,word [rsi]

	lsl ax,bx
	lsl ax,[rsi]
	lsl ax,word [rsi]
	lsl eax,bx
	lsl eax,[rsi]
	lsl eax,word [rsi]
	lsl rax,bx
	lsl rax,[rsi]
	lsl rax,word [rsi]


Add armips patch to fix the vanilla PoR death softlock

.nds
.relativeinclude on
.erroronwarning on

; Fixes a vanilla bug where skipping the cutscene after you kill Death too quickly will prevent Death's boss death flag from being set.
; As a result of that bug the boss doors would relock after you exit the room, though Death himself wouldn't ever be fightable again.

.open "ftc/overlay9_64", 022D7900h

.org 0x022D8B18
  nop

.close


Add patch to make spells always act fully charged

.nds
.relativeinclude on
.erroronwarning on

.open "ftc/overlay9_0", 021CDF60h

; This patch makes Charlotte always use spells at full power, even when only half-charged.

.org 0x02214DC8 ; Where the base multiplier for a spell is located (usually 1).
  addne r2, r4, 2h ; Change it to 2.

.org 0x021F1C40 ; Where the bonus multiplier you get for fully charging a spell is located (usually 1).
  ;movge r0, 0h ; Change it to 0. This is so fully charging a spell won't get a 3x multiplier, and instead it will stay at simply 2x (fully charged).
; You can remove the above two lines if you want fully charged spells to have a 3x multiplier, which actually does work correctly, making spells do 3x damage, and depending on the spell can even do other things like increasing the number of projectiles or the size of the projectiles past the normal limit.
; There are a few minor bugs if you choose to have spells with a 3x multiplier. For example, Spirit of Light will fire only 1 projectile instead of 3 like you'd expect, Ice Needles will all be grouped together instead of spread out among a circle, and Nightmare will use the smaller size instead of the bigger one.

.close


Add patch to always show drop percentages in PoR

.nds
.relativeinclude on
.erroronwarning on

; This patch causes you to always have the Gambler Glasses effect of showing percentages instead of star ratings for enemy drops.

.open "ftc/arm9.bin", 02000000h

.org 0x02053074 ; Checks if you have Gambler Glasses equipped to see if it should hide the stars.
  mov r0, 2h ; Head armor 2, Gambler Glasses
.org 0x02053790 ; Checks if you have Gambler Glasses equipped to see if it should show the percentages.
  mov r0, 2h ; Head armor 2, Gambler Glasses

.close


Add ARMIPS patch to disable sliding puzzle

.nds
.relativeinclude on
.erroronwarning on

; Disables the special doors of the sliding puzzle in Demon Guest House.

.open "ftc/arm9.bin", 02000000h

.org 0x0202738C
  ; This is where, upon going through any door, the game would start checking your current sector/room indexes to see if the door you went through was a sliding puzzle door.
  ; The original code here had a return that was conditional and only ran if your sector index is not 1 (Demon Guest House).
  ; We change it to an unconditional return so the special behavior of the sliding puzzle doors never activates.
  mov r0, 0h
  pop r4-r8,r14
  bx r14

.close


//============================================================
// color washer routine
//============================================================

colwash:
    lda color+$00      // load the current first color from table
    sta color+$28      // store in in last position of table to reset the cycle
    ldx #$00           // init X with zero

cycle1:
    lda color+1,x      // Start cycle by fetching next color in the table...
    sta color,x        // ...and store it in the current active position.
    sta $d990,x        // put into Color Ram
    inx                // increment X-Register
    cpx #$28           // have we done 40 iterations yet?
    bne cycle1         // if no, continue

colwash2:
    lda color2+$28     // load current last color from second table
    sta color2+$00     // store in in first position of table to reset the cycle
    ldx #$28

cycle2:
    lda color2-1,x     // Start cycle by fetching previous color in the table...
    sta color2,x       // ...and store it in the current active position.
    sta $d9df,x        // put into Color Ram
    dex                // decrease iterator
    bne cycle2         // if x not zero yet, continue

    rts                // return from subroutine

Fix last position offset on colorwasher fx

//============================================================
// color washer routine
//============================================================

colwash:
    lda color+$00      // load the current first color from table
    sta color+$27      // store in in last position of table to reset the cycle
    ldx #$00           // init X with zero

cycle1:
    lda color+1,x      // Start cycle by fetching next color in the table...
    sta color,x        // ...and store it in the current active position.
    sta $d990,x        // put into Color Ram
    inx                // increment X-Register
    cpx #$28           // have we done 40 iterations yet?
    bne cycle1         // if no, continue

colwash2:
    lda color2+$27     // load current last color from second table
    sta color2+$00     // store in in first position of table to reset the cycle
    ldx #$28

cycle2:
    lda color2-1,x     // Start cycle by fetching previous color in the table...
    sta color2,x       // ...and store it in the current active position.
    sta $d9df,x        // put into Color Ram
    dex                // decrease iterator
    bne cycle2         // if x not zero yet, continue

    rts                // return from subroutine


[BITS 64]

%include "src/asm_routines/constants.asm"

global start
extern rust_main

section .entry
start:
    ; update segments
    mov dx, gdt_selector_data   ; data selector
    mov ss, dx  ; stack segment
    mov ds, dx  ; data segment
    mov es, dx  ; extra segment
    mov fs, dx  ; f-segment
    mov gs, dx  ; g-segment

    ; set up stack
    mov esp, stack_top

    ; get to kernel
    call rust_main

    ; rust main returned, print `OS returned!`
    mov rax, 0x4f724f204f534f4f
    mov [0xb8000], rax
    mov rax, 0x4f724f754f744f65
    mov [0xb8008], rax
    mov rax, 0x4f214f644f654f6e
    mov [0xb8010], rax
    hlt

; reserve space for stack
section .bss
stack_bottom:
    resb 4096
stack_top:

Use rsp as stack pointer, not esp

[BITS 64]

%include "src/asm_routines/constants.asm"

global start
extern rust_main

section .entry
start:
    ; update segments
    mov dx, gdt_selector_data   ; data selector
    mov ss, dx  ; stack segment
    mov ds, dx  ; data segment
    mov es, dx  ; extra segment
    mov fs, dx  ; f-segment
    mov gs, dx  ; g-segment

    ; set up stack
    mov rsp, stack_top

    ; get to kernel
    call rust_main

    ; rust main returned, print `OS returned!`
    mov rax, 0x4f724f204f534f4f
    mov [0xb8000], rax
    mov rax, 0x4f724f754f744f65
    mov [0xb8008], rax
    mov rax, 0x4f214f644f654f6e
    mov [0xb8010], rax
    hlt

; reserve space for stack
section .bss
stack_bottom:
    resb 4096
stack_top:


; JUMP.ASM
; Make a jump and then hang

; Tell the compiler that this is offset 0.
; It isn't offset 0, but it will be after the jump.
[ORG 0]

        jmp 07C0h:start         ; Goto segment 07C0

start:
        ; Update the segment registers
        mov ax, cs
        mov ds, ax
        mov es, ax

hang:                           ; Hang!
        jmp hang

times 510-($-$$) db 0
dw 0AA55h

Print "===" to the screen

; 1.ASM
; Print "====" on the screen and hang

; Tell the compiler that this is offset 0.
; It isn't offset 0, but it will be after the jump.
[ORG 0]

        jmp 07C0h:start     ; Goto segment 07C0

start:
        ; Update the segment registers
        mov ax, cs
        mov ds, ax
        mov es, ax

        mov ah, 9           ; Print "===="
        mov al, '='         ;
        mov bx, 7           ;
        mov cx, 4           ;
        int 10h             ;

hang:                       ; Hang!
        jmp hang

times 510-($-$$) db 0
dw 0AA55h


Add a test for various 32- and 64-bit relocations

bits 64
	extern foo

	mov eax,[foo]
	mov rax,[foo]
	mov rax,[qword foo]

	mov eax,foo
	mov rax,dword foo
	mov rax,qword foo

	dd foo
	dq foo


bits 32
section .text
    align   4
    dd      0x1BADB002
    dd      0x00
    dd    - (0x1BADB002 + 0x00)

global start
extern main

start:
    cli
    mov     esp, kstack
    call    main
    hlt

section .bss
resb    8192
kstack:

Change name of entry function

bits 32
section .text
    align   4
    dd      0x1BADB002
    dd      0x00
    dd    - (0x1BADB002 + 0x00)

global start
extern entry

start:
    cli
    mov     esp, kstack
    call    entry
    hlt

section .bss
resb    8192
kstack:


Add patch to add holes into the doors on the map for DoS

.nds
.relativeinclude on
.erroronwarning on

; This adds a single pixel hole to all doors drawn on the map to increase visibility, like in PoR and OoE.

@Overlay41Start equ 0x02308920
@FreeSpace equ @Overlay41Start + 0x108

.open "ftc/arm9.bin", 02000000h

.org 0x020240B0
  ; Handles drawing left/right doors on the left edge of even-numbered columns.
  bne @DrawLeftRightDoorEvenColumn
  nop
  nop

.org 0x020240FC
  ; Handles drawing left/right doors on the left edge of odd-numbered columns.
  bne @DrawLeftRightDoorOddColumn
  nop
  nop

.org 0x020242A8
  ; Handles drawing up/down doors in even-numbered columns.
  ; 3 is the index of the door color in the palette, while 1 is the index of the room fill color in the palette.
  .word 0x00003133
.org 0x020242B4
  ; Handles drawing up/down doors in odd-numbered columns.
  .word 0x31330000

.close

.open "ftc/overlay9_41", @Overlay41Start

.org @FreeSpace
@DrawLeftRightDoorEvenColumn:
  cmp r4, 2 ; On the center pixel of an even-numbered row, skip drawing the door pixel
  beq 2024138h
  cmp r4, 6 ; On the center pixel of an odd-numbered row, skip drawing the door pixel
  beq 2024138h

  ; If we're not on a center pixel, simply draw the door pixel like the original code did and return.
  orr r0, r0, 3h
  str r0, [r5, r4, lsl 2h]
  b 2024138h
@DrawLeftRightDoorOddColumn:
  cmp r4, 2 ; On the center pixel of an even-numbered row, skip drawing the door pixel
  beq 2024138h
  cmp r4, 6 ; On the center pixel of an odd-numbered row, skip drawing the door pixel
  beq 2024138h

  ; If we're not on a center pixel, simply draw the door pixel like the original code did and return.
  orr r0, r0, 30000h
  str r0, [r5, r4, lsl 2h]
  b 2024138h

.close


.nds
.relativeinclude on
.erroronwarning on

.open "ftc/overlay9_0", 0219E3E0h

; This makes it so that all melee weapons can break balore blocks, not just Julius's whip.

.org 0x02212AB0 ; Branch of a switch statement taken for all melee weapons except Julius's whip.
  b 02212D64h ; Instead take the branch taken for Julius's whip.

.close

Update patch to break balore blocks

.nds
.relativeinclude on
.erroronwarning on

.open "ftc/overlay9_0", 0219E3E0h

; This makes it so that all melee weapons can break balore blocks, not just Julius's whip.

.org 0x02212AB0 ; Branch of a switch statement taken for all melee weapons except Julius's whip.
  b 02212D64h ; Instead take the branch taken for Julius's whip.

; Next we need to make sure the player has Balore's soul.

.org 0x02212E94 ; Line in the whip code that would normally call 021D5210 to break the blocks.
  b @CheckDestroyBaloreBlocks ; Instead jump to our own code to check if the player has Balore's soul.

.close

.open "ftc/arm9.bin", 02000000h

.org 0x020C0290 ; Free space
@CheckDestroyBaloreBlocks:
  mov r5, r14
  mov r0, 0h
  bl 0220F81Ch
  cmp r0, 1h ; Check if Balore soul is active.
  beq @DestroyBaloreBlocks ; Destroy blocks if it is.
  ldr r0,=020F740Eh
  ldrb r0, [r0]
  cmp r0, 1h ; Otherwise check if the current player character is Julius.
  beq @DestroyBaloreBlocks ; Destroy blocks if it is.
  b 02212E98h ; Didn't meet either condition, so return without destroying them.
@DestroyBaloreBlocks:
  mov r0, r5
  mov r1, r12
  mov r2, r4
  bl 021D5210h ; Call function to destroy blocks.
  b 02212E98h ; Return
  .pool

.close


add $t0, $t1, $t2
sub $s0, $t0, $v0
exit
beq $3, $8, 3
nop
nop

Remove the branch for clarity

add $t0, $t1, $t2
sub $s0, $t0, $v0
exit
add $t0, $t1, $t2
nop
nop


.nds
.relativeinclude on
.erroronwarning on

.open "ftc/arm9.bin", 02000000h

.org 0x02051F90 ; Where the original game's code for loading area/sector/room indexes is.
  b 020BFC00h ; Jump to some free space, where we will put our own code for loading the area/sector/room indexes.

.org 0x020BFC00 ; Free space.
  mov r5,0h        ; Load the area index into r5.
  strb r5,[r0,515h] ; Store the area index to the ram address where r0 will read it later. (0x02111785)
  mov r5,0h        ; Load the sector index into r5.
  mov r4,0h        ; Load the room index into r4.
  b 02051F94h      ; Return to where we came from.

.close

Fix changing starting room in PoR not changing Old Axe Armor mode's starting room

.nds
.relativeinclude on
.erroronwarning on

.open "ftc/arm9.bin", 02000000h

.org 0x02051F90 ; Where the original game's code for loading area/sector/room indexes is.
  b 020BFC00h ; Jump to some free space, where we will put our own code for loading the area/sector/room indexes.

.org 0x020BFC00 ; Free space.
  mov r5,0h        ; Load the area index into r5.
  strb r5,[r0,515h] ; Store the area index to the ram address where r0 will read it later. (0x02111785)
  mov r5,0h        ; Load the sector index into r5.
  mov r4,0h        ; Load the room index into r4.
  b 02051F94h      ; Return to where we came from.

.org 0x02051F80 ; The case statement for Old Axe Armor mode's starting room initialization.
  b 0x02051F88 ; Change it to take the same branch as the other three modes.

.close


bits 64
	jmp rcx
	call [rax]
	call qword [rdx]

Add more 64-bit jump tests

;Testname=test; Arguments=-fbin -ojmp64.bin; Files=.stdout .stderr jmp64.bin

	bits 64
	jmp rcx
	jmp [rax]
	jmp qword [rax]
	jmp far [rax]
	jmp far dword [rax]
	jmp far qword [rax]
	call rcx
	call [rax]
	call qword [rax]
	call far [rax]
	call far dword [rax]
	call far qword [rax]


;;----------------------------------------------------------------------------;;
;;  Align the position of the textbox in the effect of items
;;  Copyright 2014 Benito Palacios (aka pleonex)
;;
;;  Licensed under the Apache License, Version 2.0 (the "License");
;;  you may not use this file except in compliance with the License.
;;  You may obtain a copy of the License at
;;
;;      http://www.apache.org/licenses/LICENSE-2.0
;;
;;  Unless required by applicable law or agreed to in writing, software
;;  distributed under the License is distributed on an "AS IS" BASIS,
;;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;  See the License for the specific language governing permissions and
;;  limitations under the License.
;;----------------------------------------------------------------------------;;

.thumb
;; Item effect
.org 0x02117D4E
  MOV    R1, #0x60 ; X POS -> Original 0x62

;; Slot color
.org 0x021170DE
  MOV    R1, #0x9E - 4 ; X POS

.thumb
;; Increase the size of the item name textbox
.org 0x02116E90
  MOV     R0, #0x14 + 1     ; Width / 8

Increase items name textbox size

;;----------------------------------------------------------------------------;;
;;  Align the position of the textbox in the effect of items
;;  Copyright 2014 Benito Palacios (aka pleonex)
;;
;;  Licensed under the Apache License, Version 2.0 (the "License");
;;  you may not use this file except in compliance with the License.
;;  You may obtain a copy of the License at
;;
;;      http://www.apache.org/licenses/LICENSE-2.0
;;
;;  Unless required by applicable law or agreed to in writing, software
;;  distributed under the License is distributed on an "AS IS" BASIS,
;;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;  See the License for the specific language governing permissions and
;;  limitations under the License.
;;----------------------------------------------------------------------------;;

.thumb
;; Item effect
.org 0x02117D4E
  MOV    R1, #0x60 ; X POS -> Original 0x62

;; Slot color
.org 0x021170DE
  MOV    R1, #0x9E - 4 ; X POS

.thumb
;; Increase the size of the item name textbox
.org 0x02116E90
  MOV     R0, #0x14 + 2     ; Width / 8


global _start

section .data
    align 16
mydword:
    dd  0

%include "header.inc"

    ; 32-bit register move should set higher bits to zero
    mov eax, -1
    mov eax, ss
    and eax, 0xffff0000

    ; 32-bit memory move should preserver higher bits
    mov dword [mydword], 0xdeadbeef
    mov [mydword], ss
    mov ebx, [mydword]
    and ebx, 0xffff0000

%include "footer.inc"


Add patch to reveal whole map from the start for DoS

.nds
.relativeinclude on
.erroronwarning on

; Makes the entire map visible but greyed out from the start.

.open "ftc/arm9.bin", 02000000h

.org 0x020220C4
  ; Make the game not care if you have the map items and just always draw unvisited tiles.
  mov r1, r8
  nop

.org 0x02024BE8
  ; Makes rooms never be counted as secret rooms, since secret rooms don't show up even if the game thinks you have the map for that area.
  mvn r0, 0h
  bx r14

.close


; =============================================================================
; Copyright (C) 2015 Manolis Fragkiskos Ragkousis -- see LICENSE.TXT
; =============================================================================

;;; Print routine
;;; I push all the register to the stack.
;;; Set the bios routine for printing in the screen
;;; Move to al the data that bx points
;;; Generate the interrupt.
;;; Pop all registers from the stack
;;; Return to where the pc pointed to before getting in here.
;;; bx contains routine argument

%ifndef PRINT_STRING_16BIT
%define PRINT_STRING_16BIT

print_string:
        pusha
        mov ah, 0x0e

compare:
        cmp byte [bx], 0
        je exit
        jmp print

print:
        mov al, [bx]
        int 0x10
        add bx, 1
        jmp compare

exit:
        popa
        ret
%endif

Rewrite the 16bit print routine.

; =============================================================================
; Copyright (C) 2015 Manolis Fragkiskos Ragkousis -- see LICENSE.TXT
; =============================================================================

;;; Print routine
;;; I push all the register to the stack.
;;; Set the bios routine for printing in the screen
;;; Move to al the data that bx points
;;; Generate the interrupt.
;;; Pop all registers from the stack
;;; Return to where the pc pointed to before getting in here.
;;; bx contains routine argument

%ifndef PRINT_STRING_16BIT
%define PRINT_STRING_16BIT

[bits 16]
print_string:
        pusha
        mov ah, 0x0e

print_loop:
        mov al, [bx]
        cmp al, 0
        je print_exit

        int 0x10
        inc bx
        jmp print_loop

print_exit:
        popa
        ret
%endif


list n_IItemRenderer
GETSTATIC net/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer.instance : Lnet/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer;
ALOAD 1
INVOKEVIRTUAL net/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer.renderByItem (Lnet/minecraft/item/ItemStack;)V
GOTO LEND #end of if statement

list IItemRenderer
ALOAD 2
INSTANCEOF codechicken/lib/render/IItemRenderer
IFEQ LELSE
ALOAD 2
ALOAD 1
INVOKEINTERFACE codechicken/lib/render/IItemRenderer.renderItem (Lnet/minecraft/item/ItemStack;)V
GOTO LEND
LELSE

Fix srg mapping in hook (round 2)

list n_IItemRenderer
GETSTATIC net/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer.field_147719_a : Lnet/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer;
ALOAD 1
INVOKEVIRTUAL net/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer.func_179022_a (Lnet/minecraft/item/ItemStack;)V
GOTO LEND #end of if statement

list IItemRenderer
ALOAD 2
INSTANCEOF codechicken/lib/render/IItemRenderer
IFEQ LELSE
ALOAD 2
ALOAD 1
INVOKEINTERFACE codechicken/lib/render/IItemRenderer.renderItem (Lnet/minecraft/item/ItemStack;)V
GOTO LEND
LELSE


Add patch to fix DoS tower boss in boss rando

.nds
.relativeinclude on
.erroronwarning on

; This patch for the boss randomizer prevents the boss in Gergoth's tower from being loaded in until the player enters the top floor of the tower.
; In order for the patch to work correctly, the boss entity should be at index 1 and the tower floors entity should be at index 0 (reversed from how they are in vanilla).

@Overlay41Start equ 0x02308920
@FreeSpace equ @Overlay41Start + 0x288

.open "ftc/overlay9_0", 0219E3E0h

.org 0x0219F08C ; Near the end of the create function for object 18 (tower floors)
  b @LoadOrUnloadTowerBoss

.close

.open "ftc/overlay9_41", @Overlay41Start

.org @FreeSpace
@LoadOrUnloadTowerBoss:
  ldr r1, =020F70CCh ; Pointer to the current room's entity list
  ldr r1, [r1]
  add r1, r1, 11h ; Add 0x11 (0xC + 0x5) to the start of the entity list to get a pointer to the type byte of the second entity in the list, which is the boss entity.

  ; The last check done before the custom code was checking if r0 is equal to 0. If it is it means the player is on the top floor of the tower, so the boss should be loaded.
  beq @AllowTowerBossToBeLoaded
@DoNotAllowTowerBossToBeLoaded:
  mov r0, 0h ; Set the type of the boss entity to 0, so it's doesn't load any entity in.
  b @FinishLoadingOrUnloadingTowerBoss
@AllowTowerBossToBeLoaded:
  mov r0, 1h ; Set the type of the boss entity to 0, so it works properly as an enemy.
@FinishLoadingOrUnloadingTowerBoss:
  strb r0, [r1] ; Store the type to the entity list.

  ; Replace the code we overwrote to jump here.
  beq 0x0219F0AC ; Return from function if on the top floor.
  b 0x0219F098 ; If not on the top floor, do some other stuff before returning.

.pool

.close


Add basic background cycler example that is confirmed to work with 6502.Net.

.cpu "6502"
.target "flat"
* = $F000

BackgroundColor = $80

VSYNC = $00
VBLANK = $01
WSYNC = $02
COLUBK = $09
TIM64T = $296
INTIM = $284

Start
	SEI
	CLD
	LDX #$FF
	TXS
	LDA #0
ClearMem
	STA 0,X
	DEX
	BNE ClearMem
MainLoop
	LDA #%00000010
	STA VSYNC
	STA WSYNC
	STA WSYNC
	STA WSYNC
	LDA #43
	STA TIM64T
	LDA #0
	STA VSYNC

	INC BackgroundColor
	LDA BackgroundColor
	STA COLUBK

WaitForVBlankEnd
	LDA INTIM
	BNE WaitForVBlankEnd
	STA WSYNC
	STA VBLANK
	LDY #192

ScanLoop
	STA WSYNC
	DEY
	BNE ScanLoop

	LDA #2
	STA WSYNC
	STA VBLANK
	LDY #30
OverScanWait
	STA WSYNC
	DEY
	BNE OverScanWait
	JMP MainLoop

// Special memory locations. Tells the 6502 where to go.
* = $FFFC
.word Start
.word Start


Test of some addressing modes in 64-bit mode.

bits	64
	mov	rdx,[rax]
	mov	eax,[byte rsp+0x01]
	mov	eax,[byte rsp-0x01]
	mov	eax,[byte rsp+0xFF]
	mov	eax,[byte rsp-0xFF]
	mov	eax,[rsp+0x08]
	mov	eax,[rsp-0x01]
	mov	eax,[rsp+0xFF]
	mov	eax,[rsp-0xFF]
	mov	rax,[rsp+56]
	mov	[rsi],dl
	mov	byte [rsi],'-'
	mov	[rsi],al
	mov	byte [rsi],' '


;; Known problematic floating-point numbers and their proper
	;; encoding...

		dd 1.1e10
		dd 0x5023e9ac	; Should be...

		dd 50.40e9
		dd 0x513bc130	; Should be...

		dq 1.4e23
		dq 0x44bda56a4b0835c0

		dq 50.48e21
		dq 0x44a5610d7502feae

		dt 1.2e28
		dq 0x9b18ab5df7180b6c
		dw 0x405c

		dt 50.46e25
		dq 0xd0b29a67e95dcb60
		dw 0x4057


Add test cases for IP-relative addressing

bits 64
;	extern foo
	mov rax,[foo]
	mov rax,[123456789abcdef0h]
	mov rbx,[foo]
	mov rax,[dword foo]
	mov rbx,[dword foo]
	mov rax,[qword foo]
	mov rax,[rel foo]
	mov rbx,[rel foo]
	mov rax,[rel dword foo]
	mov rax,[rel qword foo]

	mov rax,[es:foo]
	mov rax,[es:123456789abcdef0h]
	mov rbx,[es:foo]
	mov rax,[dword es:foo]
	mov rbx,[dword es:foo]
	mov rax,[qword es:foo]
	mov rax,[rel es:foo]
	mov rbx,[rel es:foo]
	mov rax,[rel dword es:foo]
	mov rax,[rel qword es:foo]

	mov rax,[fs:foo]
	mov rax,[fs:123456789abcdef0h]
	mov rbx,[fs:foo]
	mov rax,[dword fs:foo]
	mov rbx,[dword fs:foo]
	mov rax,[qword fs:foo]
	mov rax,[rel fs:foo]
	mov rbx,[rel fs:foo]
	mov rax,[rel dword fs:foo]
	mov rax,[rel qword fs:foo]

	section .data
foo	equ $


; Copyright 2011 Google Inc.
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;

.286
.MODEL TINY, C

.CODE

PUBLIC end_dos_stub

begin_dos_stub PROC
  ; Fold the code and data segments, as our data is in this function.
  ; Note that begin_dos_stub is implicitly the start of the data segment.
  push cs
  pop ds

  ; Compute  the distance to the string through this subtraction instead
  ; of e.g. a lea instruction to avoid the need for relocation entries
  mov dx, message - begin_dos_stub
  ; Print the message to the console
  mov ah, 09h
  int 21h

  ; Terminate the program
  mov ah, 00h
  int 21h

  message DB 'This is a Windows program, you cannot run it in DOS.\r\n$'

  ; Expose the end of the DOS stub as a function to make it easy to
  ; calculate its length.
  end_dos_stub LABEL PROC

begin_dos_stub ENDP

END

Switch dos stub processor spec to 386.

; Copyright 2012 Google Inc.
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;

.386
.MODEL TINY, C

.CODE

PUBLIC end_dos_stub

begin_dos_stub PROC
  ; Fold the code and data segments, as our data is in this function.
  ; Note that begin_dos_stub is implicitly the start of the data segment.
  push cs
  pop ds

  ; Compute  the distance to the string through this subtraction instead
  ; of e.g. a lea instruction to avoid the need for relocation entries
  mov dx, message - begin_dos_stub
  ; Print the message to the console
  mov ah, 09h
  int 21h

  ; Terminate the program
  mov ah, 00h
  int 21h

  message DB 'This is a Windows program, you cannot run it in DOS.\r\n$'

  ; Expose the end of the DOS stub as a function to make it easy to
  ; calculate its length.
  end_dos_stub LABEL PROC

begin_dos_stub ENDP

END


module Data.Char.Gen where

import Prelude

import Control.Monad.Gen (class MonadGen, chooseInt)
import Data.Char as C

-- | Generates a character of the Unicode basic multilingual plain.
genUnicodeChar :: forall m. MonadGen m => m Char
genUnicodeChar = C.fromCharCode <$> chooseInt 0 65536

-- | Generates a character in the ASCII character set, excluding control codes.
genAsciiChar :: forall m. MonadGen m => m Char
genAsciiChar = C.fromCharCode <$> chooseInt 32 127

-- | Generates a character in the ASCII character set.
genAsciiChar' :: forall m. MonadGen m => m Char
genAsciiChar' = C.fromCharCode <$> chooseInt 0 127

-- | Generates a character that is a numeric digit.
genDigitChar :: forall m. MonadGen m => m Char
genDigitChar = C.fromCharCode <$> chooseInt 48 57

Add some additional common character generators

module Data.Char.Gen where

import Prelude

import Control.Monad.Gen (class MonadGen, chooseInt, oneOf)
import Data.Char as C
import Data.NonEmpty ((:|))

-- | Generates a character of the Unicode basic multilingual plain.
genUnicodeChar :: forall m. MonadGen m => m Char
genUnicodeChar = C.fromCharCode <$> chooseInt 0 65536

-- | Generates a character in the ASCII character set, excluding control codes.
genAsciiChar :: forall m. MonadGen m => m Char
genAsciiChar = C.fromCharCode <$> chooseInt 32 127

-- | Generates a character in the ASCII character set.
genAsciiChar' :: forall m. MonadGen m => m Char
genAsciiChar' = C.fromCharCode <$> chooseInt 0 127

-- | Generates a character that is a numeric digit.
genDigitChar :: forall m. MonadGen m => m Char
genDigitChar = C.fromCharCode <$> chooseInt 48 57

-- | Generates a character from the basic latin alphabet.
genAlpha :: forall m. MonadGen m => m Char
genAlpha = oneOf (genAlphaLowercase :| [genAlphaUppercase])

-- | Generates a lowercase character from the basic latin alphabet.
genAlphaLowercase :: forall m. MonadGen m => m Char
genAlphaLowercase = C.fromCharCode <$> chooseInt 97 122

-- | Generates an uppercase character from the basic latin alphabet.
genAlphaUppercase :: forall m. MonadGen m => m Char
genAlphaUppercase = C.fromCharCode <$> chooseInt 65 90


module Data.Ord.Unsafe (unsafeCompare) where

import Data.Ordering (Ordering(..))

unsafeCompare :: forall a. a -> a -> Ordering
unsafeCompare = unsafeCompareImpl LT EQ GT

foreign import unsafeCompareImpl
  :: forall a
   . Ordering
  -> Ordering
  -> Ordering
  -> a
  -> a
  -> Ordering

Add deprecation warning to unsafeCompare

module Data.Ord.Unsafe (unsafeCompare) where

import Prim.TypeError (class Warn, Text)
import Data.Ordering (Ordering(..))

unsafeCompare
    :: forall a.
       Warn (Text "'unsafeCompare' is deprecated.")
    => a -> a -> Ordering
unsafeCompare = unsafeCompareImpl LT EQ GT

foreign import unsafeCompareImpl
  :: forall a
   . Ordering
  -> Ordering
  -> Ordering
  -> a
  -> a
  -> Ordering


module Language.PureScript.Options where

import Prelude
import Data.Maybe

-- |
-- The data type of compiler options
--
data Options = Options {
    -- |
    -- Perform tail-call elimination
    --
    optionsTco :: Boolean
    -- |
    -- Perform type checks at runtime
    --
  , optionsPerformRuntimeTypeChecks :: Boolean
    -- |
    -- Inline calls to ret and bind for the Eff monad
    --
  , optionsMagicDo :: Boolean
    -- |
    -- When specified, checks the type of `main` in the module, and generate a call to run main
    -- after the module definitions.
    --
  , optionsMain :: Maybe String
    -- |
    -- Skip all optimizations
    --
  , optionsNoOptimizations :: Boolean
    -- |
    -- Specify the namespace that PureScript modules will be exported to when running in the
    -- browser.
    --
  , optionsBrowserNamespace :: String
    -- |
    -- The modules to keep while enabling dead code elimination
    --
  , optionsModules :: [String]
    -- |
    -- The modules to code gen
    --
  , optionsCodeGenModules :: [String]
  }

-- |
-- Default compiler options
--
defaultOptions :: Options
defaultOptions = Options { optionsTco: false
                         , optionsPerformRuntimeTypeChecks: false
                         , optionsMagicDo: false
                         , optionsMain: Nothing
                         , optionsNoOptimizations: false
                         , optionsBrowserNamespace: "PS"
                         , optionsModules: []
                         , optionsCodeGenModules: []
                         }

Update options to match latest psc

module Language.PureScript.Options where

import Data.Maybe

-- |
-- The data type of compiler options
--
data Options = Options {
    -- |
    -- Disable inclusion of the built in Prelude
    --
    optionsNoPrelude :: Boolean
    -- |
    -- Disable tail-call elimination
    --
  , optionsNoTco :: Boolean
    -- |
    -- Perform type checks at runtime
    --
  , optionsPerformRuntimeTypeChecks :: Boolean
    -- |
    -- Disable inlining of calls to return and bind for the Eff monad
    --
  , optionsNoMagicDo :: Boolean
    -- |
    -- When specified, checks the type of `main` in the module, and generate a call to run main
    -- after the module definitions.
    --
  , optionsMain :: Maybe String
    -- |
    -- Skip all optimizations
    --
  , optionsNoOptimizations :: Boolean
    -- |
    -- Specify the namespace that PureScript modules will be exported to when running in the
    -- browser.
    --
  , optionsBrowserNamespace :: Maybe String
    -- |
    -- The modules to keep while enabling dead code elimination
    --
  , optionsModules :: [String]
    -- |
    -- The modules to code gen
    --
  , optionsCodeGenModules :: [String]
    -- |
    -- Verbose error message
    --
  , optionsVerboseErrors :: Boolean
  }

-- |
-- Default compiler options
--
defaultOptions :: Options
defaultOptions = Options { optionsNoPrelude: false
                         , optionsNoTco: false
                         , optionsPerformRuntimeTypeChecks: false
                         , optionsNoMagicDo: false
                         , optionsMain: Nothing
                         , optionsNoOptimizations: false
                         , optionsBrowserNamespace: Nothing
                         , optionsModules: []
                         , optionsCodeGenModules: []
                         , optionsVerboseErrors: false
                         }


module Test.Spec.Runner (
  Process(..),
  run
  ) where

import Prelude

import Control.Monad             (when)
import Control.Monad.Aff         (runAff)
import Control.Monad.Eff         (Eff())
import Control.Monad.Eff.Console (CONSOLE(), print)
import Data.Foldable             (sequence_)

import Test.Spec          (Spec(), collect)
import Test.Spec.Console  (withAttrs)
import Test.Spec.Summary  (successful)
import Test.Spec.Reporter (Reporter())

foreign import data Process :: !

foreign import exit :: forall eff. Int -> Eff (process :: Process | eff) Unit

-- Runs the tests and invoke all reporters.
-- If run in a NodeJS environment any failed test will cause the
-- process to exit with a non-zero exit code.
run :: forall e.
    Array (Reporter (process :: Process, console :: CONSOLE | e))
    -> Spec (process :: Process, console :: CONSOLE | e) Unit
    -> Eff  (process :: Process, console :: CONSOLE | e) Unit
run rs spec = do
  runAff
    (\err -> do withAttrs [31] $ print err
                exit 1)
    (\results -> do sequence_ (map (\f -> f results) rs)
                    when (not $ successful results) $ exit 1)
    (collect spec)

Exit NodeJS process on success as well as failure.

module Test.Spec.Runner (
  Process(..),
  run
  ) where

import Prelude

import Control.Monad.Aff         (runAff)
import Control.Monad.Eff         (Eff())
import Control.Monad.Eff.Console (CONSOLE(), print)
import Data.Foldable             (sequence_)

import Test.Spec          (Spec(), collect)
import Test.Spec.Console  (withAttrs)
import Test.Spec.Summary  (successful)
import Test.Spec.Reporter (Reporter())

foreign import data Process :: !

foreign import exit :: forall eff. Int -> Eff (process :: Process | eff) Unit

-- Runs the tests and invoke all reporters.
-- If run in a NodeJS environment any failed test will cause the
-- process to exit with a non-zero exit code. On success it will
-- exit with a zero exit code explicitly, so passing integration tests that still have
-- connections open can run in CI successfully.
run :: forall e.
    Array (Reporter (process :: Process, console :: CONSOLE | e))
    -> Spec (process :: Process, console :: CONSOLE | e) Unit
    -> Eff  (process :: Process, console :: CONSOLE | e) Unit
run rs spec = do
  runAff
    (\err -> do withAttrs [31] $ print err
                exit 1)
    (\results -> do sequence_ (map (\f -> f results) rs)
                    exitWithCode (successful results))
    (collect spec)

exitWithCode :: forall t5.
  Boolean
  -> Eff ( process :: Process | t5) Unit
exitWithCode success = exit (code success)
  where code true  = 0
	code false = 1


module DOM.HTML.History where

import Control.Monad.Eff (Eff)
import DOM.HTML.Types (HISTORY, History, Window)
import Prelude (Unit)

-- DocumentTitle will set value of `document.title`
newtype DocumentTitle = DocumentTitle String
newtype Delta = Delta Int
newtype URL = URL String -- Unsure how to better type this.

foreign import back :: forall e. History -> Eff (history :: HISTORY | e) Unit
foreign import forward :: forall e. History -> Eff (history :: HISTORY | e) Unit
foreign import go :: forall e. History -> Delta -> Eff (history :: HISTORY | e) Unit
foreign import pushState :: forall a e. History -> a -> DocumentTitle -> URL -> Eff (history :: HISTORY | e) Unit
foreign import replaceState :: forall a e. History -> a -> DocumentTitle -> URL -> Eff (history :: HISTORY | e) Unit
foreign import state :: forall a e. History -> Eff (history :: HISTORY | e) a

Use Foreign instead of polymorphic a.

module DOM.HTML.History where

import Control.Monad.Eff (Eff)
import DOM.HTML.Types (HISTORY, History)
import Data.Foreign (Foreign)
import Prelude (Unit)

-- DocumentTitle will set value of `document.title`
newtype DocumentTitle = DocumentTitle String
newtype Delta = Delta Int
newtype URL = URL String -- Unsure how to better type this.

foreign import back :: forall e. History -> Eff (history :: HISTORY | e) Unit
foreign import forward :: forall e. History -> Eff (history :: HISTORY | e) Unit
foreign import go :: forall e. History -> Delta -> Eff (history :: HISTORY | e) Unit
foreign import pushState :: forall e. History -> Foreign -> DocumentTitle -> URL -> Eff (history :: HISTORY | e) Unit
foreign import replaceState :: forall e. History -> Foreign -> DocumentTitle -> URL -> Eff (history :: HISTORY | e) Unit
foreign import state :: forall e. History -> Eff (history :: HISTORY | e) Foreign


module Test.Spec.Color where

import Prelude ((<<<))

data Color
 = Pass
 | Fail
 | Pending
 | Suite
 | ErrorTitle
 | ErrorMessage
 | ErrorStack
 | Checkmark
 | Fast
 | Medium
 | Slow
 | Green
 | Light

code :: Color -> Int
code Pass         = 90
code Fail         = 31
code Pending      = 36
code Suite        = 0
code ErrorTitle   = 0
code ErrorMessage = 31
code ErrorStack   = 90
code Checkmark    = 32
code Fast         = 90
code Medium       = 33
code Slow         = 31
code Green        = 32
code Light        = 90

colored :: Color -> String -> String
colored = _colored <<< code

foreign import _colored :: Int -> String -> String

Use 'dim' code in place of 'gray'

module Test.Spec.Color where

import Prelude ((<<<))

data Color
 = Pass
 | Fail
 | Pending
 | Suite
 | ErrorTitle
 | ErrorMessage
 | ErrorStack
 | Checkmark
 | Fast
 | Medium
 | Slow
 | Green
 | Light

code :: Color -> Int
code Pass         = 2
code Fail         = 31
code Pending      = 36
code Suite        = 0
code ErrorTitle   = 0
code ErrorMessage = 31
code ErrorStack   = 2
code Checkmark    = 32
code Fast         = 2
code Medium       = 33
code Slow         = 31
code Green        = 32
code Light        = 2

colored :: Color -> String -> String
colored = _colored <<< code

foreign import _colored :: Int -> String -> String


module Data.Void (Void, absurd) where

import Data.Show (class Show)

-- | An uninhabited data type. In other words, one can never create
-- | a runtime value of type `Void` becaue no such value exists.
-- |
-- | `Void` is useful to eliminate the possibility of a value being created.
-- | For example, a value of type `Either Void Boolean` can never have
-- | a Left value created in PureScript.
-- |
-- | This should not be confused with the word, `void,` that commonly appears in
-- | C-deriving languages, such as Java:
-- | ```
-- | public class Foo {
-- |   void doSomething() { System.out.println("hello world!"); }
-- | }
-- | ```
-- |
-- | In PureScript, one often uses `Unit` to achieve similar effects as
-- | the lowercased `void` above.
newtype Void = Void Void

instance showVoid :: Show Void where
  show = absurd

-- | Eliminator for the `Void` type.
-- | Useful for stating that some code branch is impossible because you've
-- | "acquired" a value of type `Void` (which you can't).
-- |
-- | ```purescript
-- | rightOnly :: forall t . Either Void t -> t
-- | rightOnly (Left v) = absurd v
-- | rightOnly (Right t) = t
-- | ```
absurd :: forall a. Void -> a
absurd a = spin a
  where
  spin (Void b) = spin b

Use "C-family" rather than "C-deriving" rendering

module Data.Void (Void, absurd) where

import Data.Show (class Show)

-- | An uninhabited data type. In other words, one can never create
-- | a runtime value of type `Void` becaue no such value exists.
-- |
-- | `Void` is useful to eliminate the possibility of a value being created.
-- | For example, a value of type `Either Void Boolean` can never have
-- | a Left value created in PureScript.
-- |
-- | This should not be confused with the word, `void,` that commonly appears in
-- | C-family languages, such as Java:
-- | ```
-- | public class Foo {
-- |   void doSomething() { System.out.println("hello world!"); }
-- | }
-- | ```
-- |
-- | In PureScript, one often uses `Unit` to achieve similar effects as
-- | the lowercased `void` above.
newtype Void = Void Void

instance showVoid :: Show Void where
  show = absurd

-- | Eliminator for the `Void` type.
-- | Useful for stating that some code branch is impossible because you've
-- | "acquired" a value of type `Void` (which you can't).
-- |
-- | ```purescript
-- | rightOnly :: forall t . Either Void t -> t
-- | rightOnly (Left v) = absurd v
-- | rightOnly (Right t) = t
-- | ```
absurd :: forall a. Void -> a
absurd a = spin a
  where
  spin (Void b) = spin b


module Web.Firebase.Types (
     DataSnapshot
   , Firebase
   , FirebaseEff
   , FirebaseErr
   , Key)
where

-- in process of moving the to string conversion function here, as it belongs with the typeclass
import Prelude (class Show, class Eq, (==))

foreign import data FirebaseEff :: !

foreign import data Firebase :: *
foreign import data FirebaseErr :: *

foreign import firebaseErrToString :: FirebaseErr -> String

instance showFirebaseErr :: Show FirebaseErr where
  show err = firebaseErrToString err

instance eqFirebaseErr :: Eq FirebaseErr where
  eq e1 e2 = (firebaseErrToString e1) == (firebaseErrToString e2)

{-
  https://www.firebase.com/docs/web/guide/user-auth.html#section-handling-errors:
  All errors are Error objects containing at least code and message attributes. In some cases, additional information will be provided via the details attribute. For example:
  {
	    code: "TRANSPORT_UNAVAILABLE",
       message: "There are no login transports available for the requested method.",
         details: "More details about the specific error here."
 }
-}

--https://www.firebase.com/docs/web/api/datasnapshot/
foreign import data DataSnapshot :: *

type Key = String

Upgrade Effect and Type from ! and *

module Web.Firebase.Types (
     DataSnapshot
   , Firebase
   , FirebaseEff
   , FirebaseErr
   , Key)
where

-- in process of moving the to string conversion function here, as it belongs with the typeclass
import Control.Monad.Eff (kind Effect)
import Prelude (class Show, class Eq, (==))

foreign import data FirebaseEff :: Effect

foreign import data Firebase :: Type
foreign import data FirebaseErr :: Type

foreign import firebaseErrToString :: FirebaseErr -> String

instance showFirebaseErr :: Show FirebaseErr where
  show err = firebaseErrToString err

instance eqFirebaseErr :: Eq FirebaseErr where
  eq e1 e2 = (firebaseErrToString e1) == (firebaseErrToString e2)

{-
  https://www.firebase.com/docs/web/guide/user-auth.html#section-handling-errors:
  All errors are Error objects containing at least code and message attributes. In some cases, additional information will be provided via the details attribute. For example:
  {
	    code: "TRANSPORT_UNAVAILABLE",
       message: "There are no login transports available for the requested method.",
         details: "More details about the specific error here."
 }
-}

--https://www.firebase.com/docs/web/api/datasnapshot/
foreign import data DataSnapshot :: Type

type Key = String


module Control.Monad.Cont.Extras where

import Data.Array ()
import Data.Maybe
import Data.Tuple

import Control.Monad
import Control.Monad.Eff
import Control.Monad.Eff.Ref

import Control.Monad.Trans
import Control.Monad.Cont.Trans

type WithRef eff = Eff (ref :: Ref | eff)

type ContRef eff = ContT Unit (WithRef eff)

foldC :: forall eff a r. (r -> a -> Tuple Boolean r) -> r -> ContRef eff a -> ContRef eff r
foldC f r0 c = do
  current <- lift $ newRef r0
  callCC $ \k -> do
    a <- c
    r <- lift $ readRef current
    case f r a of
      Tuple emit next -> do
        when emit $ k next
        quietly $ lift $ writeRef current next

  where
  quietly :: forall m a. (Monad m) => ContT Unit m Unit -> ContT Unit m a
  quietly = withContT (\_ _ -> return unit)

collect :: forall eff a. ContRef eff (Maybe a) -> ContRef eff [a]
collect = foldC f []
  where
  f xs Nothing = Tuple true xs
  f xs (Just x) = Tuple false (xs ++ [x])

Use quietly at the top level

module Control.Monad.Cont.Extras where

import Data.Array ()
import Data.Maybe
import Data.Tuple

import Control.Monad
import Control.Monad.Eff
import Control.Monad.Eff.Ref

import Control.Monad.Trans
import Control.Monad.Cont.Trans

type WithRef eff = Eff (ref :: Ref | eff)

type ContRef eff = ContT Unit (WithRef eff)

foldC :: forall eff a r. (r -> a -> Tuple Boolean r) -> r -> ContRef eff a -> ContRef eff r
foldC f r0 c = do
  current <- lift $ newRef r0
  callCC $ \k -> quietly $ do
    a <- c
    r <- lift $ readRef current
    case f r a of
      Tuple emit next -> do
        when emit $ k next
        lift $ writeRef current next

  where
  quietly :: forall m a. (Monad m) => ContT Unit m Unit -> ContT Unit m a
  quietly = withContT (\_ _ -> return unit)

collect :: forall eff a. ContRef eff (Maybe a) -> ContRef eff [a]
collect = foldC f []
  where
  f xs Nothing = Tuple true xs
  f xs (Just x) = Tuple false (xs ++ [x])


module Api
    ( loadSnippet
    , loadSnippets
    , voteSnippetSucks
    , voteSnippetRocks
    ) where

import Control.Monad.Eff
import Control.Monad.Cont.Trans
import Control.Monad.Maybe.Trans
import Control.Monad.Trans
import Control.Plus
import Control.MonadPlus
import Data.Either
import Data.Foreign
import Data.Foreign.Class
import Data.Maybe
import Network
import Types

loadSnippet :: forall eff. Number -> MaybeT (ContT Unit (Eff eff)) Snippet
loadSnippet id = do
    response <- lift <<< get' $ "/snippet/" ++ (show id)
    guard $ response.status == 200

    let deserializedSnippet = readJSON response.text :: F Snippet
    case deserializedSnippet of
         (Right snippet) -> return snippet
         otherwise       -> empty

loadSnippets :: forall eff. ContT Unit (Eff eff) [Snippet]
loadSnippets = do
    response <- get' "/snippets"
    let deserializedSnippets = readJSON response.text :: F [Snippet]
    case deserializedSnippets of
         (Right snippets) -> return snippets
         (Left _)         -> return []

mkVoteUrl :: String -> Number -> String
mkVoteUrl v i = "/snippet/" ++ (show i) ++ "/" ++ v

voteSnippet :: forall eff. String -> Number -> ContT Unit (Eff eff) Unit
voteSnippet vote id = do
    put' $ mkVoteUrl vote id
    return unit

voteSnippetSucks :: forall eff. Number -> ContT Unit (Eff eff) Unit
voteSnippetSucks = voteSnippet "sucks"

voteSnippetRocks :: forall eff. Number -> ContT Unit (Eff eff) Unit
voteSnippetRocks = voteSnippet "rocks"

Use either instead of pattern matching

module Api
    ( loadSnippet
    , loadSnippets
    , voteSnippetSucks
    , voteSnippetRocks
    ) where

import Control.Monad.Eff
import Control.Monad.Cont.Trans
import Control.Monad.Maybe.Trans
import Control.Monad.Trans
import Control.Plus
import Control.MonadPlus
import Data.Either
import Data.Foreign
import Data.Foreign.Class
import Data.Maybe
import Network
import Types

loadSnippet :: forall eff. Number -> MaybeT (ContT Unit (Eff eff)) Snippet
loadSnippet id = do
    response <- lift <<< get' $ "/snippet/" ++ (show id)
    guard $ response.status == 200
    either (const empty) return $ readJSON response.text :: F Snippet

loadSnippets :: forall eff. ContT Unit (Eff eff) [Snippet]
loadSnippets = do
    response <- get' "/snippets"
    return $ either (const []) id $ readJSON response.text :: F [Snippet]

mkVoteUrl :: String -> Number -> String
mkVoteUrl v i = "/snippet/" ++ (show i) ++ "/" ++ v

voteSnippet :: forall eff. String -> Number -> ContT Unit (Eff eff) Unit
voteSnippet vote id = do
    put' $ mkVoteUrl vote id
    return unit

voteSnippetSucks :: forall eff. Number -> ContT Unit (Eff eff) Unit
voteSnippetSucks = voteSnippet "sucks"

voteSnippetRocks :: forall eff. Number -> ContT Unit (Eff eff) Unit
voteSnippetRocks = voteSnippet "rocks"


module Language.PureScript.Prelude where

import Node.Path

foreign import procFile "var procFile = process.argv[1];" :: String

preludeBaseDir :: String
preludeBaseDir = join (dirname procFile) "../prelude/"

preludeFiles :: [String]
preludeFiles =
  [ preludeBaseDir ++ "Prelude.purs"
  , preludeBaseDir ++ "Prelude/Unsafe.purs"
  , preludeBaseDir ++ "Control/Monad/Eff.purs"
  , preludeBaseDir ++ "Control/Monad/Eff/Unsafe.purs"
  , preludeBaseDir ++ "Control/Monad/ST.purs"
  , preludeBaseDir ++ "Data/Eq.purs"
  , preludeBaseDir ++ "Data/Function.purs"
  , preludeBaseDir ++ "Debug/Trace.purs"
  ]

Fix prelude path location for executables

module Language.PureScript.Prelude where

import Node.Path

foreign import procFile
  "var procFile = require('fs').realpathSync(process.argv[1]);" :: String

preludeBaseDir :: String
preludeBaseDir = join (dirname procFile) "../prelude/"

preludeFiles :: [String]
preludeFiles =
  [ preludeBaseDir ++ "Prelude.purs"
  , preludeBaseDir ++ "Prelude/Unsafe.purs"
  , preludeBaseDir ++ "Control/Monad/Eff.purs"
  , preludeBaseDir ++ "Control/Monad/Eff/Unsafe.purs"
  , preludeBaseDir ++ "Control/Monad/ST.purs"
  , preludeBaseDir ++ "Data/Eq.purs"
  , preludeBaseDir ++ "Data/Function.purs"
  , preludeBaseDir ++ "Debug/Trace.purs"
  ]


module Test.Data.String.Regex where

import Data.String.Regex
import Debug.Trace
import Control.Monad.Eff
import qualified Test.QuickCheck as QC

assert :: Boolean -> QC.QC {}
assert = QC.quickCheck' 1

main = do

  let r = regex "test" "g"

  trace "test 'test' matches correctly"
  assert $ test r "testing"
  trace "test 'test' reports false for a mismatch"
  assert $ not $ test r "foo"

  trace "test 'replaceR' replaces all matches"
  assert $ replaceR r "work" "testing testing 1 2 3" == "working working 1 2 3"

  trace "test 'search' finds the first match"
  assert $ search r "the string 'test' first appears in this test at index 12" == 12

  trace "test 'match' reports the correct number of matches"
  assert $ match r "test test test" == ["test", "test", "test"]

Update test for replaceR, add test for replace'

module Test.Data.String.Regex where

import Data.Array (reverse)
import Data.String (joinWith)
import Data.String.Regex
import Debug.Trace
import Control.Monad.Eff
import qualified Test.QuickCheck as QC

assert :: Boolean -> QC.QC {}
assert = QC.quickCheck' 1

main = do

  let r = regex "test" "g"

  trace "test 'test' matches correctly"
  assert $ test r "testing"
  trace "test 'test' reports false for a mismatch"
  assert $ not $ test r "foo"

  trace "test 'replace' replaces all matches"
  assert $ replace r "work" "testing testing 1 2 3" == "working working 1 2 3"

  trace "test 'replace'' replaces matches with a function"
  assert $ replace' (regex "(some) (test)" "") (\match groups -> joinWith " " (reverse groups)) "here are some test words" == "here are test some words"

  trace "test 'search' finds the first match"
  assert $ search r "the string 'test' first appears in this test at index 12" == 12

  trace "test 'match' reports the correct number of matches"
  assert $ match r "test test test" == ["test", "test", "test"]


module Debug.Profile where

import Prelude
import Debug.Trace
import Control.Monad.Eff
import Control.Monad.Eff.Console
import Control.Monad.Eff.Unsafe
import Text.Parsing.Parser (PState(..), ParserT(..), unParserT) as P

prof :: ∀ m a. (Monad m) => String -> (Unit -> m a) -> m a
prof = profileA

profileA :: ∀ m a. (Monad m) => String -> (Unit -> m a) -> m a
profileA msg f = do
  let t  = unsafePerformEff timerStart
  a <- f unit
  let t' = unsafePerformEff $ timerEnd t
  traceA $ msg <> " (" <> (show t') <> " ms)"
  pure a

profileParser :: ∀ s m a. (Monad m) => String -> P.ParserT s m a -> P.ParserT s m a
profileParser msg p = P.ParserT $ \s -> profileA msg \_ -> P.unParserT p s

foreign import timerStart :: ∀ eff. Eff eff Int
foreign import timerEnd :: ∀ eff. Int -> Eff eff Int

Add switch to toggle profile output

module Debug.Profile where

import Prelude
import Debug.Trace
import Control.Monad.Eff
import Control.Monad.Eff.Console
import Control.Monad.Eff.Unsafe
import Text.Parsing.Parser (PState(..), ParserT(..), unParserT) as P

_ENABLE_PROFILING_ :: Boolean
_ENABLE_PROFILING_ = false

prof :: ∀ m a. (Monad m) => String -> (Unit -> m a) -> m a
prof = profileA

profileA :: ∀ m a. (Monad m) => String -> (Unit -> m a) -> m a
profileA msg f =
  if _ENABLE_PROFILING_
    then do
      let t  = unsafePerformEff timerStart
      a <- f unit
      let t' = unsafePerformEff $ timerEnd t
      traceA $ msg <> " (" <> (show t') <> " ms)"
      pure a
    else f unit

profileParser :: ∀ s m a. (Monad m) => String -> P.ParserT s m a -> P.ParserT s m a
profileParser msg p = P.ParserT $ \s -> profileA msg \_ -> P.unParserT p s

foreign import timerStart :: ∀ eff. Eff eff Int
foreign import timerEnd :: ∀ eff. Int -> Eff eff Int


module Neodoc.Solve where

import Prelude
import Debug.Trace
import Data.Either (Either(..), either)
import Neodoc.Spec
import Neodoc.Spec as Spec
import Neodoc.Data.UsageLayout
import Neodoc.Data.SolvedLayout
import Neodoc.Solve.Error
import Neodoc.Solve.SmartOptions as Solve
import Neodoc.Solve.ExpandOptions as Solve
import Neodoc.Solve.ExpandReferences as Solve
import Neodoc.Solve.Canonicalise as Solve

type SolveOptions r = {
  smartOptions :: Boolean
  | r
}

solve
  :: ∀ r
   .  SolveOptions r
  -> Spec UsageLayout
  -> Either SolveError (Spec SolvedLayout)
solve { smartOptions } spec = pure spec
    >>= (if smartOptions then Solve.smartOptions else pure)
    >>= Solve.expandOptions
    >>= Solve.expandReferences
    >>= Solve.canonicalise

Allow plugging in custom transforms in purescript

module Neodoc.Solve where

import Prelude
import Debug.Trace
import Data.Either (Either(..), either)
import Data.List (List(..))
import Data.List as List
import Data.Foldable (class Foldable)
import Data.Traversable (for)
import Neodoc.Spec
import Neodoc.Spec as Spec
import Neodoc.Data.UsageLayout
import Neodoc.Data.SolvedLayout
import Neodoc.Solve.Error
import Neodoc.Solve.SmartOptions as Solve
import Neodoc.Solve.ExpandOptions as Solve
import Neodoc.Solve.ExpandReferences as Solve
import Neodoc.Solve.Canonicalise as Solve

type SolveOptions r = {
  smartOptions :: Boolean
  | r
}

solve'
  :: ∀ r
   . SolveOptions r
  -> List (Spec UsageLayout  -> Either SolveError (Spec UsageLayout))
  -> List (Spec SolvedLayout -> Either SolveError (Spec SolvedLayout))
  -> Spec UsageLayout
  -> Either SolveError (Spec SolvedLayout)
solve' { smartOptions } usageTs solvedTs =
      (if smartOptions then Solve.smartOptions else pure)
  >=> flip (List.foldM (#)) usageTs
  >=> Solve.expandOptions
  >=> Solve.expandReferences
  >=> Solve.canonicalise
  >=> flip (List.foldM (#)) solvedTs

solve
  :: ∀ r
   . SolveOptions r
  -> Spec UsageLayout
  -> Either SolveError (Spec SolvedLayout)
solve opts = solve' opts Nil Nil


module Data.String.Ext (
    (^=)
  , endsWith
  ) where

import Prelude
import Debug.Trace
import Data.Maybe (maybe)
import Data.String as Str
import Data.Function

(^=) :: String -> String -> Boolean
(^=) = eq `on` Str.toUpper

endsWith :: String -> String -> Boolean
endsWith needle haystack = maybe false id do
  ix <- Str.lastIndexOf needle haystack
  return $ ix == (Str.length haystack - Str.length needle)

Add negation operator for `(^=)`

module Data.String.Ext (
    (^=), (^/=)
  , endsWith
  ) where

import Prelude
import Debug.Trace
import Data.Maybe (maybe)
import Data.String as Str
import Data.Function

(^=) :: String -> String -> Boolean
(^=) = eq `on` Str.toUpper

(^/=) :: String -> String -> Boolean
(^/=) a b = not (a ^= b)

endsWith :: String -> String -> Boolean
endsWith needle haystack = maybe false id do
  ix <- Str.lastIndexOf needle haystack
  return $ ix == (Str.length haystack - Str.length needle)


module Main where

import qualified Control.Monad.JQuery as J
import           Control.Monad.Eff
import DOM

import Data.Either

import Web
import Parser
import Evaluator
import AST

import Debug.Trace

main = J.ready $ do
  print "Hello world!"
  let expr = case parseExpr "1 + 2 * 3 + 4 * 5 * 6" of Right e -> e
  let env = defsToEnv $ case parseDefs "double x = x + x" of Right d -> d
  showExpr expr
  return unit

showExpr :: forall eff. Expr -> Eff (dom :: DOM | eff) Unit
showExpr expr = do
  test <- J.select "#test"
  J.clear test
  jexpr <- exprToJQuery expr showExpr
  J.append jexpr test
  return unit

Change hardcoded testing example *rolls eyes*

module Main where

import qualified Control.Monad.JQuery as J
import           Control.Monad.Eff
import DOM

import Data.Either

import Web
import Parser
import Evaluator
import AST

import Debug.Trace

main = J.ready $ do
  print "Hello world!"
  let expr = case parseExpr "1 : (1 + 2) : [3 * 4, 9 `div` 3]" of Right e -> e
  let env = defsToEnv $ case parseDefs "double x = x + x" of Right d -> d
  showExpr expr
  return unit

showExpr :: forall eff. Expr -> Eff (dom :: DOM | eff) Unit
showExpr expr = do
  test <- J.select "#test"
  J.clear test
  jexpr <- exprToJQuery expr showExpr
  J.append jexpr test
  return unit


module Main (main) where

import Prelude
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Console (CONSOLE, log)
import Data.Array as A
import Data.List (List)
import Data.Traversable (for)

import Types (Cube(..))
import Solver (solve)
import Levels (levelTitle, getLevel, getChapter, allLevelIds)

ttyColor :: Cube -> Int
ttyColor Yellow = 0
ttyColor Orange = 1
ttyColor Brown = 2
ttyColor Red = 3
ttyColor Cyan = 4

showList :: forall a. (Show a) => List a -> String
showList xs = show (A.fromFoldable xs :: Array a)

showList2 :: forall a. (Show a) => List (List a) -> String
showList2 xss = show ((A.fromFoldable <<< map A.fromFoldable) xss :: Array (Array a))

main :: forall eff. Eff (console :: CONSOLE | eff) Unit
main = void do
    for allLevelIds $ \lid -> do
        let chapter = getChapter lid
            level = getLevel lid
            solutions = solve lid

        log $ levelTitle lid level
        log $ "  Initial: " <> showList2 (map (map ttyColor) level.initial)
        log $ "  Target:  " <> showList2 (map (map ttyColor) level.target)
        log $ "  Solutions: "
        for solutions $ \sol ->
            log $ "    " <> showList sol
        log ""

Update CLI solver to PS 0.11

module Main (main) where

import Prelude
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Console (CONSOLE, log)
import Data.Array as A
import Data.List (List)
import Data.Traversable (for, for_)

import Types (Cube(..))
import Solver (solve)
import Levels (levelTitle, getLevel, getChapter, allLevelIds)

ttyColor :: Cube -> Int
ttyColor Yellow = 0
ttyColor Orange = 1
ttyColor Brown = 2
ttyColor Red = 3
ttyColor Cyan = 4

showList :: forall a. (Show a) => List a -> String
showList xs = show (A.fromFoldable xs :: Array a)

showList2 :: forall a. (Show a) => List (List a) -> String
showList2 xss = show ((A.fromFoldable <<< map A.fromFoldable) xss :: Array (Array a))

main :: forall eff. Eff (console :: CONSOLE | eff) Unit
main = void do
    for allLevelIds $ \lid -> do
        let chapter = getChapter lid
            level = getLevel lid
            solutions = solve lid

        log $ levelTitle lid level
        log $ "  Initial: " <> showList2 (map (map ttyColor) level.initial)
        log $ "  Target:  " <> showList2 (map (map ttyColor) level.target)
        log $ "  Solutions: "
        for_ solutions $ \sol ->
            log $ "    " <> showList sol
        log ""


module Explorer.View.Calculator where

import Prelude

import Pux.Html (Html, div, text) as P
import Pux.Html.Attributes (className) as P
import Pux.Router (link) as P

import Explorer.I18n.Lang (translate)
import Explorer.I18n.Lenses (cBack, cCalculator, common) as I18nL
import Explorer.Types.State (State)
import Explorer.Types.Actions (Action)
import Explorer.Routes (Route(Dashboard), toUrl)
import Explorer.View.Common (placeholderView)

calculatorView :: State -> P.Html Action
calculatorView state =
    P.div
        [ P.className "explorer-calculator" ]
        [ P.div
            [ P.className "explorer-calculator__container" ]
            [ P.link (toUrl Dashboard)
                [ P.className "" ]
                [ P.text $ translate (I18nL.common <<< I18nL.cBack) state.lang ]
            , placeholderView $ translate (I18nL.common <<< I18nL.cCalculator) state.lang
            ]
        ]

Update `calculator` view to `psc 0.11.x`

module Explorer.View.Calculator where

import Prelude

import Explorer.I18n.Lang (translate)
import Explorer.I18n.Lenses (cBack, cCalculator, common) as I18nL
import Explorer.Types.State (State)
import Explorer.Types.Actions (Action)
import Explorer.Routes (Route(Dashboard), toUrl)
import Explorer.View.Common (placeholderView)

import Text.Smolder.HTML (div, a)
import Text.Smolder.HTML.Attributes (className, href)
import Text.Smolder.Markup (text, (#!), (!))

import Pux.DOM.HTML (Html) as P

calculatorView :: State -> P.Html Action
calculatorView state =
    div ! className "explorer-calculator" $ do
        div
            ! className "explorer-calculator__container" $ do
            a
                ! href (toUrl Dashboard)
                ! className ""
                #! onClick (toUrl Dashboard)
                $ text (translate (I18nL.common <<< I18nL.cBack) state.lang)
            placeholderView $ translate (I18nL.common <<< I18nL.cCalculator) state.lang


module Entries.Notebook where

import App.Notebook (app)
import Data.Tuple (Tuple(..))
import Halogen (runUI)
import Utils (onLoad, mountUI)
import qualified Driver.Notebook as D

main = onLoad $ void $ do
  Tuple node driver <- runUI app
  mountUI node
  D.driver driver

Add type to notebook app

module Entries.Notebook where

import App.Notebook (app)
import Control.Monad.Eff (Eff())
import Data.Tuple (Tuple(..))
import EffectTypes (NotebookAppEff())
import Halogen (runUI)
import Utils (onLoad, mountUI)
import qualified Driver.Notebook as D

main :: Eff (NotebookAppEff ()) Unit
main = onLoad $ void $ do
  Tuple node driver <- runUI app
  mountUI node
  D.driver driver


module Main where

import Debug.Trace

import Data.Either

import Control.Apply

import Language.PureScript.Parser.Lexer
import Language.PureScript.Parser.Common
import Language.PureScript.Parser.Declarations

import Language.PureScript.Supply
import Language.PureScript.Sugar

example =
  "module Test where\n\
  \\n\
  \  foo :: Number -> Number\n\
  \  foo 0 = 1\n\
  \  foo 1 = 0\n\
  \  foo n = n"

main = do
  trace "Lexing source file"
  case lex example of
    Left err -> trace err
    Right tokens -> do
      trace $ "Tokens: " ++ show tokens
      trace "Parsing module"
      case runTokenParser (parseModule <* eof) tokens of
        Left err -> trace err
        Right mod -> do
          trace $ "Module: " ++ show mod
          trace "Desugaring module"
          case evalSupplyT 0 (desugar [mod]) of
            Left err -> print err
            Right [mod'] -> do
              trace $ "Desugared: " ++ show mod'

Add type checking and code gen to the test

module Main where

import Debug.Trace

import Data.Maybe
import Data.Tuple
import Data.Either

import Control.Apply
import Control.Monad.Identity

import Language.PureScript.Declarations
import Language.PureScript.Supply
import Language.PureScript.Sugar
import Language.PureScript.TypeChecker
import Language.PureScript.TypeChecker.Monad
import Language.PureScript.Environment
import Language.PureScript.Options
import Language.PureScript.CodeGen.JS
import Language.PureScript.Supply

import qualified Language.PureScript.Parser.Lexer as P
import qualified Language.PureScript.Parser.Common as P
import qualified Language.PureScript.Parser.Declarations as P

example =
  "module Test where\n\
  \\n\
  \  foo :: Number -> Number\n\
  \  foo 0 = 1\n\
  \  foo 1 = 0\n\
  \  foo n = n"

main = do
  trace "Lexing source file"
  case P.lex example of
    Left err -> trace err
    Right tokens -> do
      trace $ "Tokens: " ++ show tokens
      trace "Parsing module"
      case P.runTokenParser (P.parseModule <* P.eof) tokens of
        Left err -> trace err
        Right mod -> do
          trace $ "Module: " ++ show mod
          trace "Desugaring module"
          case evalSupplyT 0 (desugar [mod]) of
            Left err -> print err
            Right [mod'@(Module mn ds exps)] -> do
              trace $ "Desugared: " ++ show mod'
              trace "Type checking and elaborating terms"
              case runCheck defaultOptions (typeCheckAll Nothing mn ds) of
                Left err -> print err
                Right (Tuple ds' env) -> do
                  trace $ "Elaborated: "++ show ds'
                  trace "Generating code"
                  case runIdentity (evalSupplyT 0 (moduleToJs CommonJS defaultOptions (Module mn ds' exps) env)) of
                    jss -> trace $ "Generated JS: " ++ show jss


module Test.Main where

import Prelude
import Control.Monad.Eff (Eff)
import Test.Unit (suite, test)
import Test.Unit.Main (runTest)
import Test.Unit.Assert as Assert
import Data.List (List, fromFoldable)
import Data.String as String
import Accumulate (accumulate)

main :: Eff _ Unit
main = runTest do
  suite "Accumulate.accumulate" do
    test "empty accumulation" $
      let
        emptyList = (fromFoldable [] :: List Int)
      in
        Assert.equal emptyList $
          accumulate square emptyList

    test "accumulate single square" $
      Assert.equal (fromFoldable [4]) $
        accumulate square (fromFoldable [2])

    test "accumulate squares" $
      Assert.equal (fromFoldable [1, 4, 9]) $
        accumulate square (fromFoldable [1, 2, 3])

    test "accumulate upcases" $
      Assert.equal (fromFoldable ["HELLO", "WORLD"]) $
        accumulate String.toUpper (fromFoldable ["hello", "world"])

    test "accumulate length of strings" $
      Assert.equal (fromFoldable [3, 5, 5, 3, 3]) $
        accumulate String.length (fromFoldable ["the", "quick", "brown", "fox", "etc"])

square :: forall a. (Semiring a) => a -> a
square x = x * x

Use Nil for empty list in test.

module Test.Main where

import Prelude
import Control.Monad.Eff (Eff)
import Test.Unit (suite, test)
import Test.Unit.Main (runTest)
import Test.Unit.Assert as Assert
import Data.List (List(Nil), fromFoldable)
import Data.String as String
import Accumulate (accumulate)

main :: Eff _ Unit
main = runTest do
  suite "Accumulate.accumulate" do
    test "empty accumulation" $
      let
        emptyList = (Nil :: List Int)
      in
        Assert.equal emptyList $
          accumulate square emptyList

    test "accumulate single square" $
      Assert.equal (fromFoldable [4]) $
        accumulate square (fromFoldable [2])

    test "accumulate squares" $
      Assert.equal (fromFoldable [1, 4, 9]) $
        accumulate square (fromFoldable [1, 2, 3])

    test "accumulate upcases" $
      Assert.equal (fromFoldable ["HELLO", "WORLD"]) $
        accumulate String.toUpper (fromFoldable ["hello", "world"])

    test "accumulate length of strings" $
      Assert.equal (fromFoldable [3, 5, 5, 3, 3]) $
        accumulate String.length (fromFoldable ["the", "quick", "brown", "fox", "etc"])

square :: forall a. (Semiring a) => a -> a
square x = x * x


module Tab
  ( Cell
  ) where

import Prelude
import Data.Maybe (Maybe(..))
import Data.Vec
import Data.List
import Data.Typelevel.Num

class ColType a where
  kind :: a

instance stringCol :: ColType String where
  kind = ""

type Cell a = Maybe a

class Conv a where
  conv :: ColType a => a -> Cell a

instance convAny :: Conv a where
  conv x = Just x

newtype Table size cols cells = Table
  { columns :: Vec size cols
  , rows :: List (Vec size cells)
  }

Add Col for columns to new try

module Tab
  ( Cell
  , Col
  , class ColType
  , kind
  ) where

import Prelude
import Data.Maybe (Maybe(..))
import Data.Vec
import Data.List
import Data.Typelevel.Num

type Col x = ColType x =>
  { id :: Int
  , name :: String
  , kind :: x
  }

class ColType a where
  kind :: a

instance stringCol :: ColType String where
  kind = ""

type Cell a = Maybe a

class Conv a where
  conv :: ColType a => a -> Cell a

instance convAny :: Conv a where
  conv x = Just x

newtype Table size cols cells = Table
  { columns :: Vec size cols
  , rows :: List (Vec size cells)
  }


module Main where

import Prelude

import App.Env (appEnvConfig)
import App.Routing (Location(Verify), routing)
import App.State (AppEffects, Event(..), State, InitEnv, foldp, init)
import App.State.Contracts (buildAccountsChannel, buildAccountsSignal)
import App.State.Locations (buildRoutingSignal)
import App.View (view)
import Control.Monad.Eff (Eff)
import Pux (App, CoreEffects, start)
import Pux.DOM.Events (DOMEvent)
import Pux.Renderer.React (renderToDOM)
import Routing (matches)
import Signal (Signal, constant)
import Signal.Channel (channel, send)

type WebApp = App (DOMEvent -> Event) Event State
type AllEffects = Eff (CoreEffects AppEffects)

foreign import load :: Unit

initApp :: InitEnv -> Signal Event
initApp env = constant $ Init env

-- | Start and render the app
main :: String -> State -> AllEffects WebApp
main url state = do
  routingChannel <- channel Verify
  ethAccountChannel <- buildAccountsChannel

  let
    initSignal = initApp { ethAccountChannel }
    routingSignal = Routing <$> buildRoutingSignal routingChannel
    ethAccountsSignal = Contract <$> buildAccountsSignal ethAccountChannel

  app <- start
    { initialState: state
    , view
    , foldp
    , inputs:
      [ initSignal
      , routingSignal
      , ethAccountsSignal
      ]
    }

  renderToDOM "#app" app.markup app.input

  matches routing \old new -> send routingChannel new

  pure app

initialState :: State
initialState = init appEnvConfig

Read initial page from state

module Main where

import Prelude

import App.Env (appEnvConfig)
import App.Routing (routing)
import App.State (AppEffects, Event(..), State, InitEnv, foldp, init)
import App.State.Contracts (buildAccountsChannel, buildAccountsSignal)
import App.State.Locations (buildRoutingSignal)
import App.View (view)
import Control.Monad.Eff (Eff)
import Pux (App, CoreEffects, start)
import Pux.DOM.Events (DOMEvent)
import Pux.Renderer.React (renderToDOM)
import Routing (matches)
import Signal (Signal, constant)
import Signal.Channel (channel, send)

type WebApp = App (DOMEvent -> Event) Event State
type AllEffects = Eff (CoreEffects AppEffects)

foreign import load :: Unit

initApp :: InitEnv -> Signal Event
initApp env = constant $ Init env

-- | Start and render the app
main :: String -> State -> AllEffects WebApp
main url state = do
  routingChannel <- channel state.location
  ethAccountChannel <- buildAccountsChannel

  let
    initSignal = initApp { ethAccountChannel }
    routingSignal = Routing <$> buildRoutingSignal routingChannel
    ethAccountsSignal = Contract <$> buildAccountsSignal ethAccountChannel

  app <- start
    { initialState: state
    , view
    , foldp
    , inputs:
      [ initSignal
      , routingSignal
      , ethAccountsSignal
      ]
    }

  renderToDOM "#app" app.markup app.input

  matches routing \old new -> send routingChannel new

  pure app

initialState :: State
initialState = init appEnvConfig


module Pagination where

import Prelude (map, (<=), ($), show, (>), (&&), (<>), (-), (>=), otherwise, (+))
import Data.Array ((..))
import Data.Show (class Show)

mapToString :: forall a. ( Show a ) => Array a -> Array String
mapToString = map show

paginate :: Int -> Int -> Array String
paginate page activep
    | page <= 10                = mapToString $ 1..page
    | page > 10 && activep <= 5 = (mapToString $ 1..7) <> [".."] <> (mapToString [page-1, page])
    | activep >= page -5        = (mapToString $ 1..2) <> [".."] <> (mapToString $ (page-6)..page)
    | otherwise                 = (mapToString $ 1..2)
                                    <> [".."]
                                    <> (mapToString $ (activep-1)..(activep+2))
                                    <> [".."]
                                    <> (mapToString [page-1, page])

Fix when number page is null

module Pagination where

import Prelude (map, (==), (<=), ($), show, (>), (&&), (<>), (-), (>=), otherwise, (+))
import Data.Array ((..))
import Data.Show (class Show)

mapToString :: forall a. ( Show a ) => Array a -> Array String
mapToString = map show

paginate :: Int -> Int -> Array String
paginate page activep
    | page == 0                 = []
    | page <= 10                = mapToString $ 1..page
    | page > 10 && activep <= 5 = (mapToString $ 1..7) <> [".."] <> (mapToString [page-1, page])
    | activep >= page -5        = (mapToString $ 1..2) <> [".."] <> (mapToString $ (page-6)..page)
    | otherwise                 = (mapToString $ 1..2)
                                    <> [".."]
                                    <> (mapToString $ (activep-1)..(activep+2))
                                    <> [".."]
                                    <> (mapToString [page-1, page])


module Test.Spec.GeneratorSpec (generatorSpec) where

import Prelude
import Control.Monad.Aff (liftEff')
import Debug.Trace

import Docopt
import Docopt.Parser.Usage (Usage(..))
import qualified Docopt.Parser.Usage as Usage
import qualified Docopt.Parser.Options as Options
import qualified Docopt.Textwrap as Textwrap
import qualified Docopt.Parser.Lexer as Lexer
import qualified Docopt.Parser.Scanner as Scanner
import Docopt.Parser.Base (debug)

import Test.Assert (assert)
import Test.Spec (describe, it)
import Test.Spec.Reporter.Console (consoleReporter)
import Test.Assert.Simple
import Test.Support (vliftEff, runMaybeEff, runEitherEff)

import Control.Monad.State (State(), evalState)

generatorSpec =
  describe "options parser" do
    it "should have some tests..." do
      pure unit

Write helpers for testing generator

module Test.Spec.GeneratorSpec (generatorSpec) where

import Prelude
import Debug.Trace
import Control.Monad.Aff (liftEff')
import Control.Monad.State (State(), evalState)
import Data.Maybe (Maybe(..))
import Data.List (List(..), toList)

import Docopt
import Docopt.Parser.Usage (Usage(..))
import qualified Docopt.Parser.Usage as Usage
import qualified Docopt.Parser.Options as Options
import qualified Docopt.Textwrap as Textwrap
import qualified Docopt.Parser.Lexer as Lexer
import qualified Docopt.Parser.Scanner as Scanner
import Docopt.Parser.Base (debug)

import Test.Assert (assert)
import Test.Spec (describe, it)
import Test.Spec.Reporter.Console (consoleReporter)
import Test.Assert.Simple
import Test.Support (vliftEff, runMaybeEff, runEitherEff)

-- short hand to create a Command
co :: String -> Argument
co = Command

-- short hand to create a Positional argument
po :: String -> Boolean -> Argument
po = Positional

-- short hand to create an Option argument
opt :: (Maybe Flag)
    -> (Maybe Name)
    -> (Maybe String)
    -> (Maybe Default)
    -> IsRepeatable
    -> Argument
opt = Option

-- short hand to create a group
gr :: Boolean -> (Array (Array Argument)) -> IsRepeatable -> Argument
gr b xs = Group b (toList $ br <$> xs)

-- short hand to create a optional group
gro :: (Array (Array Argument)) -> IsRepeatable -> Argument
gro = gr true

-- short hand to create a required group
grr :: (Array (Array Argument)) -> IsRepeatable -> Argument
grr = gr false

-- short hand to create a whole branch
br :: (Array Argument) -> Branch
br xs = Branch (toList xs)

generatorSpec =
  describe "options parser" do
    it "should have some tests..." do
      pure unit


module Data.Field
  ( class Field
  , module Data.CommutativeRing
  , module Data.EuclideanRing
  , module Data.Ring
  , module Data.Semiring
  ) where

import Data.CommutativeRing (class CommutativeRing)
import Data.EuclideanRing (class EuclideanRing, degree, div, mod, (/), gcd, lcm)
import Data.Ring (class Ring, negate, sub)
import Data.Semiring (class Semiring, add, mul, one, zero, (*), (+))

-- | The `Field` class is for types that are commutative fields.
-- |
-- | Instances must satisfy the following law in addition to the
-- | `EuclideanRing` laws:
-- |
-- | - Non-zero multiplicative inverse: ``a `mod` b = zero`` for all `a` and `b`
-- |
-- | The `Unit` instance is provided for backwards compatibility, but it is
-- | not law-abiding, because `Unit` does not obey the `EuclideanRing` laws.
-- | This instance will be removed in a future release.
class EuclideanRing a <= Field a

instance fieldNumber :: Field Number

Remove out of date comment

module Data.Field
  ( class Field
  , module Data.CommutativeRing
  , module Data.EuclideanRing
  , module Data.Ring
  , module Data.Semiring
  ) where

import Data.CommutativeRing (class CommutativeRing)
import Data.EuclideanRing (class EuclideanRing, degree, div, mod, (/), gcd, lcm)
import Data.Ring (class Ring, negate, sub)
import Data.Semiring (class Semiring, add, mul, one, zero, (*), (+))

-- | The `Field` class is for types that are commutative fields.
-- |
-- | Instances must satisfy the following law in addition to the
-- | `EuclideanRing` laws:
-- |
-- | - Non-zero multiplicative inverse: ``a `mod` b = zero`` for all `a` and `b`
class EuclideanRing a <= Field a

instance fieldNumber :: Field Number


module Main (main) where

import Data.Maybe

import qualified Thermite as T
import qualified Thermite.Html as T

data Action = TextChanged String

data State = State String

initialState :: State
initialState = State ""

render :: T.Context Action -> State -> T.Html _
render ctx (State s) =
  T.createElement "p" (T.props []) $ welcome : response s
  where
  welcome :: T.Html _
  welcome =
    T.createElement "p" (T.props [])
      [ T.text "What is your name? "
      , T.createElement "input" (T.props [ T.onChange ctx TextChanged ]) []
      ]

  response :: String -> [T.Html _]
  response "" = []
  response s =
    [ T.createElement "p" (T.props [])
        [ T.text "Hello, "
        , T.text s
        ]
    ]

performAction :: State -> Action -> T.Action _ State
performAction _ (TextChanged s) k = k (State s)

spec :: T.Spec _ State Action
spec = T.Spec { initialState: initialState
              , setup: Nothing
              , performAction: performAction
              , render: render
              }

main = do
  let component = T.createClass spec
  T.render component

Fix ordering issue in example

module Main (main) where

import Data.Maybe

import qualified Thermite as T
import qualified Thermite.Html as T

data Action = TextChanged String

data State = State String

initialState :: State
initialState = State ""

render :: T.Context Action -> State -> T.Html _
render ctx (State s) =
  T.createElement "div" (T.props []) $ welcome : response s
  where
  welcome :: T.Html _
  welcome =
    T.createElement "div" (T.props [])
      [ T.text "What is your name? "
      , T.createElement "input" (T.props [ T.onChange ctx TextChanged ]) []
      ]

  response :: String -> [T.Html _]
  response "" = []
  response s =
    [ T.createElement "div" (T.props [])
        [ T.text "Hello, "
        , T.text s
        ]
    ]

performAction :: State -> Action -> T.Action _ State
performAction _ (TextChanged s) k = k (State s)

spec :: T.Spec _ State Action
spec = T.Spec { initialState: initialState
              , setup: Nothing
              , performAction: performAction
              , render: render
              }

main = do
  let component = T.createClass spec
  T.render component


module Mustache where

import Data.StrMap
import Prelude

type Template = String

type Tag = String

foreign import name :: String

foreign import version :: String

foreign import tags :: Array String

foreign import parse :: Template -> Array Tag -> Array (Array String)

foreign import render :: Template -> StrMap String -> StrMap String

foreign import escape :: String -> String

Use appropriate type for tags constant

module Mustache where

import Data.StrMap
import Prelude

type Template = String

type Tag = String

foreign import name :: String

foreign import version :: String

foreign import tags :: Array Tag

foreign import parse :: Template -> Array Tag -> Array (Array String)

foreign import render :: Template -> StrMap String -> StrMap String

foreign import escape :: String -> String


module Tab
  ( Cell
  , Col
  , class ColType
  , kind
  , Tab
  ) where

import Prelude
import Data.Maybe (Maybe(..))
import Data.Vec
import Data.Vec (empty, snoc) as Vec
import Data.List
import Data.Typelevel.Num (class Nat, class Succ, D0)

type Col x = ColType x =>
  { id :: Int
  , name :: String
  , kind :: x
  }

class ColType a where
  kind :: a

instance stringCol :: ColType String where
  kind = ""

type Cell a = Maybe a

class Conv a where
  conv :: ColType a => a -> Cell a

instance convAny :: Conv a where
  conv x = Just x

newtype Tab size cols cells = Tab
  { columns :: Vec size cols
  , rows :: List (Vec size cells)
  }

empty :: forall cols rows. Tab D0 cols rows
empty = Tab
  { columns : Vec.empty
  , rows : Nil
  }

-- addColumn :: forall s0 c0 r0 s1 c1 r1 ck. Tab s0 c0 r0 => Tab s1 c1 r1 => ColType ck => Tab s0 c0 r0 -> Col ck -> Tab s1 c1 r1
addColumn (Tab table) column = Tab
  { columns : Vec.snoc column table.columns
  , rows : map (\row -> Vec.snoc Nothing row) table.rows
  }

addRow (Tab table) row = Tab
  { columns : table.columns
  , rows : (Cons row table.rows)
  }

Add type info to addRow

module Tab
  ( Cell
  , Col
  , class ColType
  , kind
  , Tab
  ) where

import Prelude
import Data.Maybe (Maybe(..))
import Data.Vec
import Data.Vec (empty, snoc) as Vec
import Data.List
import Data.Typelevel.Num (class Nat, class Succ, D0)

type Col x = ColType x =>
  { id :: Int
  , name :: String
  , kind :: x
  }

class ColType a where
  kind :: a

instance stringCol :: ColType String where
  kind = ""

type Cell a = Maybe a

class Conv a where
  conv :: ColType a => a -> Cell a

instance convAny :: Conv a where
  conv x = Just x

newtype Tab size cols cells = Tab
  { columns :: Vec size cols
  , rows :: List (Vec size cells)
  }

empty :: forall cols rows. Tab D0 cols rows
empty = Tab
  { columns : Vec.empty
  , rows : Nil
  }

-- addColumn :: forall s0 c0 r0 s1 c1 r1 ck. Tab s0 c0 r0 => Tab s1 c1 r1 => ColType ck => Tab s0 c0 r0 -> Col ck -> Tab s1 c1 r1
addColumn (Tab table) column = Tab
  { columns : Vec.snoc column table.columns
  , rows : map (\row -> Vec.snoc Nothing row) table.rows
  }

addRow :: forall s0 c0 r. Tab s0 c0 r -> Vec s0 r -> Tab s0 c0 r
addRow (Tab table) row = Tab
  { columns : table.columns
  , rows : (Cons row table.rows)
  }


module Main where

type Foo = (x :: Number | (y :: Number | (z :: Number)))
type Bar = (x :: Number, y :: Number, z :: Number)
type Baz = { w :: Number | Bar }

foo :: { | Foo }
foo = { x: 0, y: 0, z: 0 }

bar :: { | Bar }
bar = { x: 0, y: 0, z: 0 }

id' :: Object Foo -> Object Bar
id' = id

foo' :: { | Foo }
foo' = id' foo

bar' :: { | Bar }
bar' = id' bar

baz :: Baz
baz = { x: 0, y: 0, z: 0, w: 0 }

main = Debug.Trace.trace "Done"

Add some more sophisticated cases to row constructors test suite

module Main where

type Foo = (x :: Number | (y :: Number | (z :: Number)))
type Bar = (x :: Number, y :: Number, z :: Number)
type Baz = { w :: Number | Bar }

foo :: { | Foo }
foo = { x: 0, y: 0, z: 0 }

bar :: { | Bar }
bar = { x: 0, y: 0, z: 0 }

id' :: Object Foo -> Object Bar
id' = id

foo' :: { | Foo }
foo' = id' foo

bar' :: { | Bar }
bar' = id' bar

baz :: Baz
baz = { x: 0, y: 0, z: 0, w: 0 }

type Quux r = (q :: Number | r)
type Norf r = (q' :: Number | Quux r)

quux :: { f :: { | Foo } | Quux Bar }
quux = { f: foo', x: 0, y: 0, z: 0, q: 0 }

quux' :: { | Norf Bar }
quux' = { x: 0, y: 0, z: 0, q: 0, q': 0 }

wildcard :: { w :: Number | _ } -> Baz
wildcard { w: w } = { x: w, y: w, z: w, w: w }

wildcard' :: { | Quux _ } -> Number
wildcard' { q: q } = q

main = Debug.Trace.trace "Done"


module Node.Express.Middleware.CookieParser where

import Control.Monad.Eff.Class (liftEff)
import Data.Function (($))
import Data.Function.Uncurried (Fn3, runFn3)
import Data.Unit (Unit)
import Node.Express.Handler (Handler, HandlerM(..))
import Node.Express.Types (Request, Response, ExpressM)

foreign import _cookieParser :: forall eff. Fn3 Request Response (ExpressM eff Unit) (ExpressM eff Unit)

-- | Handler that parses cookies using 'cookie-parser' middleware.
cookieParser :: forall eff. Handler eff
cookieParser = HandlerM $
  \req res nxt -> liftEff $ runFn3 _cookieParser req res nxt

Hide `_cookieParser` from module export

module Node.Express.Middleware.CookieParser
  ( cookieParser
  ) where

import Control.Monad.Eff.Class (liftEff)
import Data.Function (($))
import Data.Function.Uncurried (Fn3, runFn3)
import Data.Unit (Unit)
import Node.Express.Handler (Handler, HandlerM(..))
import Node.Express.Types (Request, Response, ExpressM)

foreign import _cookieParser :: forall eff. Fn3 Request Response (ExpressM eff Unit) (ExpressM eff Unit)

-- | Handler that parses cookies using 'cookie-parser' middleware.
cookieParser :: forall eff. Handler eff
cookieParser = HandlerM $
  \req res nxt -> liftEff $ runFn3 _cookieParser req res nxt