program test_extends()

import printf from "stdio.h"


type Parent = struct
	base: int
	x: integer
end

type Child = struct extends Parent
	y: integer
end

type Grand = struct extends Child
	z: integer
end


function returnParent(g1: Grand): Parent
begin
	var c1 = g1.base.base
	return c1
	// return g1 		// auto-upcast Grand => Parent
end


function returnParentX(g1: Grand): Parent
begin
	return g1
end


function toChild(g1: Grand): Child
begin
	return g1
end


procedure takeParentPtr(p: const ^Parent)
begin
	printf("ptr p^.x=%d\n", p^.x)
	printf("ptr p^.base=%d\n", p^.base)
	printf("ptr p.x=%d\n", p.x)
	printf("ptr p.base=%d\n", p.base)
end


procedure takeParentRef(ref r: Parent)
begin
	printf("ref r.x=%d\n", r.x)
	printf("ref r.base=%d\n", r.base)
end


begin
	var c: Child
	var g: Grand

	var base: cardinal = 99
	printf("%u\n", base)

	c.x := 1
	c.y := 2
	printf("c.x=%d c.y=%d\n", c.x, c.y)

	c.base.base := 42
	c.base.x := 3
	printf("c.base.base=%d c.base.x=%d\n", c.base.base, c.base.x)
	printf("c.base.base=%d c.x=%d c.y=%d\n", c.base.base, c.x, c.y)

	g.base.base.base := 43
	g.x := 10
	g.y := 20
	g.z := 30
	printf("g.x=%d g.y=%d g.z=%d g.base.base.base=%d\n", g.x, g.y, g.z, g.base.base.base)

	printf("\n")

	let p = g
	let c2 = returnParent(p)
	// let p: Parent = g 			// Grand => Parent
	// let c2 = returnParent(g) 	// call-arg upcast
	printf("c2.base=%d\n", c2.base)

	let c3 = returnParentX(p)
	printf("c3.base=%d c3.x=%d\n", c3.base, c3.x)

	let c4 = toChild(g)
	printf("c4.base.base=%d c4.x=%d c4.y=%d\n", c4.base.base, c4.x, c4.y)

	let c5: ^Child = (@g) as ^Child
	printf("c5.base.base=%d c5.y=%d\n", c5^.base.base, c5^.y)
	printf("c5.x=%d c5^.base.x=%d\n", c5^.x, c5^.base.x)

	let p6 = g as Parent
	let c6 = g as Child
	printf("p6.base=%d p6.x=%d\n", p6.base, p6.x)
	printf("c6.base.base=%d c6.y=%d\n", c6.base.base, c6.y)

	let pg: ^Grand = @g
	let pp: ^Parent = pg
	printf("pp^.x=%d\n", pp^.x)

	takeParentPtr(@g)
	takeParentPtr(c5)
	takeParentRef(g)
	takeParentRef(c)

	let pp2 = (@g) as ^Parent
	printf("pp2^.x=%d\n", pp2^.x)

	printf("c5.x=%d c5.y=%d\n", c5.x, c5.y)
	printf("pp.x=%d\n", pp.x)
	printf("pp.z=%d pg.x=%d\n", pg.z, pg.x)
end

